Git Product home page Git Product logo

wsdd-native's Introduction

wsdd-native

Linux macOS FreeBSD OpenBSD NetBSD Language Standard License

A Unix daemon that makes your Linux/macOS/BSD/illumos machine visible in Network view of Windows Explorer on newer versions of Windows.

It implements WS-Discovery protocol that Windows now uses to discover machines on local network. It is a native daemon, written in C++.

Features

  • Fully supports macOS, Linux, FreeBSD, OpenBSD, NetBSD and illumos
  • Can be configured via a configuration file, not just command line.
  • Discovers Samba/macOS SMB configuration on its own. (This can be overridden, if desired)
  • Can present the Unix host as something other than "Computer" in Windows Explorer.
  • Integrates well with systemd and launchd. Of course it can also run as a classical Unix daemon for other init systems.
  • Friendly to various log rotation methods like newsyslogd and logrotate. Supports standard reload semantics via SIGHUP.
  • Written with security in mind first and foremost.
  • Will never run any network code as root. Designated user account to run under is created automatically, if needed.

There are a couple of similar projects available: wsdd written in Python and wsdd2 written in C. Neither of them, however, fully provides the features above.

The biggest drawback of wsdd-native compared to these projects is that it requires modern (as of 2022) C++ compiler to build and set of modern libc, libstdc++/libc++ etc. to run. This usually limits it to recent versions of operating systems it supports. (It is possible to build it on older ones with newer toolchains but doing so is non-trivial). Of course, as time passes this limitation will become less and less significant.

Binary packages

Ubuntu/Debian/Mint/Raspberry Pi

Pre-built packages are available in a custom apt repository for systems newer than Ubuntu 20.04 (focal) or Debian 11 (bullseye). Any Debian system based upon those or newer should work.

Architectures supported: amd64 (aka x86_64), arm64 (aka aarch64) and armhf

Setup and usage (click to expand)

To set up the apt repository:

  • Import the repository public key

    wget -qO- https://www.gershnik.com/apt-repo/conf/pgp-key.public \
      | gpg --dearmor \
      | sudo tee /usr/share/keyrings/gershnik.gpg >/dev/null
  • Add new repo

    echo "deb" \
    "[arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gershnik.gpg]" \
    "https://www.gershnik.com/apt-repo/" \
    "base" \
    "main" \
      | sudo tee /etc/apt/sources.list.d/wsddn.list >/dev/null

Once the repository is set up you can install wsddn as usual via:

sudo apt update
sudo apt install wsddn

If you have UFW firewall running do

sudo ufw allow wsddn

Daemon will be enabled and started automatically on first install but keep its existing state on updates.

On systemd based distributions to start/stop/reload it use

sudo systemctl start wsddn
sudo systemctl stop wsddn
sudo systemctl reload wsddn

Configuration file will be at /etc/wsddn.conf. Comments inside indicate available options and their meaning. You can also use man wsddn to learn about configuration or see online version here

Daemon log can be viewed via journalctl as usual

journalctl -u wsddn

On non-systemd based distributions (and Docker) you can use:

sudo /etc/init.d/wsddn start
sudo /etc/init.d/wsddn stop
sudo /etc/init.d/wsddn reload

and the log is available at /var/log/wsddn.log

RedHat/CentOS/Fedora

Pre-built packages are available on Fedora Copr repository. Visit that link to see currently supported distributions and architectures.

Setup and usage (click to expand)

To set the repo up you need to install copr plugin if you haven't already done so:

sudo dnf install dnf-plugins-core
#or with yum
#sudo yum install yum-plugin-copr

Then

sudo dnf copr enable gershnik/wsddn
#or with yum
#sudo yum copr enable gershnik/wsddn

Once the repository is set up you can install wsddn as usual via

sudo dnf install wsddn
#or with yum
#sudo yum install wsddn

On first install firewall ports 5357/tcp and 3702/udp will be opened.

Enable and start the daemon:

sudo systemctl enable wsddn
sudo systemctl start wsddn

To start/stop/reload it use

sudo systemctl start wsddn
sudo systemctl stop wsddn
sudo systemctl reload wsddn

Configuration file will be at /etc/wsddn.conf. Comments inside indicate available options and their meaning. You can also use man wsddn to learn about configuration or see online version here

Daemon log can be viewed via journalctl as usual

journalctl -u wsddn

Arch Linux

Source package is available on AUR at https://aur.archlinux.org/packages/wsdd-native

Pre-built packages are available in a custom pacman repository. Only x86_64 architecture is supported.

Setup and usage (click to expand)

To set up the repository:

  1. Import the repository PGP key
sudo pacman-key --recv-keys 'CF567A58C5DB9C6908C6E87E6EBB54370005A361' \
  && sudo pacman-key --lsign-key 'CF567A58C5DB9C6908C6E87E6EBB54370005A361'
  1. Add the repository configuration to /etc/pacman.conf
[gershnik]
Server = https://www.gershnik.com/arch-repo/x86_64
  1. Refresh the package databases
sudo pacman -Sy

Once the repository is set up you can install wsdd-native as usual via:

sudo pacman -S wsdd-native

As per Arch Linux convention the installation does not automatically enable or start services.

Enable and start the daemon:

sudo systemctl enable wsddn
sudo systemctl start wsddn

To start/stop/reload it use

sudo systemctl start wsddn
sudo systemctl stop wsddn
sudo systemctl reload wsddn

Configuration file will be at /etc/wsddn.conf. Comments inside indicate available options and their meaning. You can also use man wsddn to learn about configuration or see online version here

Daemon log can be viewed via journalctl as usual

journalctl -u wsddn

Alpine

Pre-built packages are available in a custom apk repository for Alpine 3.18 or above.

Architectures supported: x86_64 andaarch64

Setup and usage (click to expand)

To set up the repository:

  1. Import the repository key
wget -qO-  https://www.gershnik.com/alpine-repo/[email protected] \
  | sudo tee /etc/apk/keys/[email protected] >/dev/null
  1. Add the repository configuration to /etc/apk/repositories
https://www.gershnik.com/alpine-repo/main
  1. Update apk
sudo apk update
  1. Install the package.
sudo apk add wsdd-native

If your Alpine system has OpenRC running (e.g. not a Docker container), OpenRC configuration will be automatically installed too. Otherwise, if desired, you can manually add it via sudo apk add wsdd-native-openrc. Similarly documentation is available via sudo apk add wsdd-native-doc.

Under OpenRC:

Enable and start the service:

sudo rc-update add wsddn
sudo rc-service wsddn start

To start/stop/reload it use

sudo rc-service wsddn start
sudo rc-service wsddn stop
sudo rc-service wsddn reload

Configuration file will be at /etc/wsddn.conf. Comments inside indicate available options and their meaning. If you installed documentation you can also use man wsddn to learn about configuration or see online version here

Log file is located at /var/log/wsddn.log. Log file rotation is configured via logrotate. To modify rotation settings edit /etc/logrotate.d/wsddn

FreeBSD

Pre-built packages are available for FreeBSD 13 and 14 in a custom binary package repository. Both amd64 (aka x86_64) and arm64 (aka aarch64) architectures are supported.

Setup and usage (click to expand)

To set the repo up:

  • Create the custom repo config folder if it does not already exist
    sudo mkdir -p /usr/local/etc/pkg/repos
  • Download the repository public key
    wget -qO- https://www.gershnik.com/bsd-repo/rsa-key.pub \
     | sudo tee /usr/local/etc/pkg/repos/www_gershnik_com.pub > /dev/null
  • Create a file named /usr/local/etc/pkg/repos/www_gershnik_com.conf
  • Put the following content in it:
    www_gershnik_com: {
        url: "https://www.gershnik.com/bsd-repo/${ABI}",
        signature_type: "pubkey",
        pubkey: "/usr/local/etc/pkg/repos/www_gershnik_com.pub",
        enabled: yes
    }
    

Once the repository is set up you can install wsddn as usual via

sudo pkg update
sudo pkg install wsddn

As is standard on FreeBSD daemon will not be enabled or started after installation. To enable it, edit /etc/rc.conf and add the following line there:

wsddn_enable="YES"

To start/stop/reload the daemon use:

sudo service wsddn start
sudo service wsddn stop
sudo service wsddn reload

Configuration file will be at /usr/local/etc/wsddn.conf. Comments inside indicate available options and their meaning. You can also use man wsddn to learn about configuration or see online version here

Log file is located at /var/log/wsddn.log. Log file rotation is configured via newsylogd. To modify rotation settings edit /usr/local/etc/newsyslog.conf.d/wsddn.conf

macOS

On macOS there are 3 ways to install wsddn: via a standalone installer package, Homebrew or Macports. Using a standalone installer is simpler but you will have to manually install any future updates as well. Homebrew/Macports are a bit more complicated to set up but it provides updatability similar to Linux/BSD package managers.

For all 3 methods the supported platforms are:

  • macOS Catalina (10.15) and above
  • Both Intel and Apple Silicon

Standalone installer

Setup and usage (click to expand)

To install via standalone .pkg installer:

If you prefer command line, you can also install via:

sudo installer -pkg /path/to/wsddn-macos-1.13.pkg -target /

To fully uninstall wsddn run /usr/local/bin/wsddn-uninstall

Daemon will start automatically on install.

To start/stop/reload the daemon use:

sudo launchctl kickstart system/io.github.gershnik.wsddn
sudo launchctl kill TERM system/io.github.gershnik.wsddn
sudo launchctl kill HUP system/io.github.gershnik.wsddn

Configuration file will be at /etc/wsddn.conf. Comments inside indicate available options and their meaning. You can also use man wsddn to learn about configuration or see online version here

Daemon and related logs can be viewed in system log by searching for subsystem or process names containing string wsddn. For example:

log show --last 15m --debug --info \
  --predicate 'subsystem CONTAINS "wsddn" OR process CONTAINS "wsddn"'

Homebrew

Setup and usage (click to expand)

Homebrew package ('cask') can be installed via a custom tap.

To set it up

brew tap gershnik/repo

Then

brew install wsddn

This installs exactly the same thing as standalone installer would so all the usage instructions under Standalone installer apply as well.

Macports

Setup and usage (click to expand)

Macports package can be installed via a custom repository.

To set the repo up:

sudo bash <<'___'
set -e
pemurl=https://gershnik.com/macports-repo/macports.pem
porturl=https://www.gershnik.com/macports-repo/ports.tar.bz2
prefix=$(dirname $(dirname $(which port)))
pemfile="$prefix/share/macports/gershnik.pem"
pubkeysfile="$prefix/etc/macports/pubkeys.conf"
sourcesfile="$prefix/etc/macports/sources.conf"
curl -s $pemurl > "$pemfile"
grep -qxF "$pemfile" "$pubkeysfile" || echo $pemfile >> "$pubkeysfile"
grep -qxF "$porturl" "$sourcesfile" || echo $porturl >> "$sourcesfile"
sudo port sync
___

Then you can install wsddn as usual via

sudo port install wsddn

Daemon will start automatically on install.

To start/stop/reload the daemon use:

sudo launchctl kickstart system/org.macports.wsddn
sudo launchctl kill TERM system/org.macports.wsddn
sudo launchctl kill HUP system/org.macports.wsddn

Configuration file will be at /opt/local/etc/wsddn.conf. Comments inside indicate available options and their meaning. You can also use man wsddn to learn about configuration or see online version here

Daemon and related logs can be viewed in system log by searching for subsystem or process names containing string wsddn. For example:

log show --last 15m --debug --info \
  --predicate 'subsystem CONTAINS "wsddn" OR process CONTAINS "wsddn"'

Building from sources

Prerequisites

  • Git
  • C++20 capable compiler. Minimal compilers known to work are GCC 10.2, Clang 13 and Xcode 13.
  • CMake 3.25 or greater. If your distribution CMake is older than that you can download a newer version from https://cmake.org/download/
  • patch tool. Most operating system distributions have it available by default by some minimalistic ones might not.
  • Optional: On Linux if you wish to enable systemd integration make sure you have libsystemd library and headers installed on your system. On APT systems use:
    sudo apt install libsystemd-dev
    On DNF systems use
    sudo dnf install systemd-devel

Building and installing

git clone https://github.com/gershnik/wsdd-native.git
cd wsdd-native
cmake -S . -B out -DCMAKE_BUILD_TYPE=RelWithDebInfo -DFETCHCONTENT_QUIET=OFF ..
cmake --build  out
sudo cmake --install out --strip

The wsddn executable will be installed into /usr/local/bin and manpage added to section 8 of the manual.

The following flags can be passed to CMake configure step:

-DWSDDN_PREFER_SYSTEM=ON|OFF

This controls whether to prefer system version of 3rd party libraries or fetch, build and use static ones. Currently only libxml2 is affected.

On Linux:

-DWSDDN_WITH_SYSTEMD="yes"|"no"|"auto".

This controls whether to enable systemd integration. Auto performs auto-detection (this is the default).

Setting up daemon

The config directory of this repo contains sample configuration files for different init systems (systemd, FreeBSD rc.d and macOS launchd). You can adapt those as appropriate to your system.

Command line flags and configuration file entries are documented in man wsddn and online here

Usage

Firewall Setup

Note: The following instructions are copied verbatim from wsdd one since the requirements are identical

Traffic for the following ports, directions and addresses must be allowed.

  • incoming and outgoing traffic to udp/3702 with multicast destination:
    • 239.255.255.250 for IPv4
    • ff02::c for IPv6
  • outgoing unicast traffic from udp/3702
  • incoming to tcp/5357

You should further restrict the traffic to the (link-)local subnet, e.g. by using the fe80::/10 address space for IPv6. Please note that IGMP traffic must be enabled in order to get IPv4 multicast traffic working.

Security

There are two main security concerns with a daemon that delivers data about local machine over the network

  1. A bug inside daemon code may allow remote attacker to penetrate the machine running it.
  2. The information legitimately provided by the daemon will disclose something to an attacker that would otherwise remain unknown, enabling him to mount further attacks.

Currently the implementation ignores the second concern. The things wsdd-native discloses are the existence of the local host, its name, presence of Samba on it and domain/workgroup membership. All of these are generally disclosed by Samba itself via SMB broadcasts so, assuming the firewall is configured as described above, there is no net gain for an attacker. WS-Discovery protocol contains provisions for encrypting its HTTP traffic and potentially authenticating clients accessing your host via their client certificates. This limits exposure somewhat but at a significant configuration and maintenance cost. If there is interest in any of it it is possible to easily add this functionality in a future version.

The first concern is by far the most significant one. All software contains bugs and despite developer's best efforts there is always a risk that a bad actor can discover some kind of input that allows him to hijack the server process. To address this possibility wsdd-native takes the following measures (apart from general secure coding practices):

  • The process performing network communications never runs as root. If launched as root it will create an unprivileged account (_wsddn:_wsddn on macOS and wsddn:wsddn on other platforms) and run network process under it.
  • Similarly when started as root the daemon will lock the network process in a chroot jail (/var/empty on macOS and /var/run/wsddn on other platforms).

These measures are automatic and cannot be bypassed. Taken together they should limit the fallout of any vulnerability though, of course, nothing ever can be claimed to be 100% secure.

Note that when running on systemd systems it is recommended to use its DynamicUser facility instead of running as root and relying on the measures above. The Debian/Ubuntu/Arch installer does so.

Custom metadata

By default wsdd-native exposes the host it is running on as a computer in "Computer" section of Windows Explorer Network view. Clicking on a computer will attempt to access its shares via SMB protocol.

Instead of this wsdd-native allows you to expose the host as a different kind of device among those supported by Windows Explorer, for example a media player, home security, printer etc. To do so you need to author a custom metadata XML and specify it via --metadata command line switch or metadata field in wsddn.conf.

More details on this can be found on this page.

Acknowledgements

wsdd-native is directly influenced by wsdd. While no source code from it was directly re-used in this project, many design and implementation ideas were; as well as command line design and some documentation content.

See Acknowledgements.md for information about open source libraries used in this project.

Reporting Bugs

Please use the GitHub issue tracker to report any bugs or suggestions. For vulnerability disclosures or other security concerns see Security Policy

wsdd-native's People

Contributors

gershnik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

wsdd-native's Issues

macOS: _wsddn user is reassigned to `staff` group on OS update

It happens reliably on every macOS update. No google hits on anything similar. Another side effect of this is that _wsddn group is left without members and then is shown in "Users and Groups" UI as available for assignment of normal users. Utterly bizarre.
Given the scenario it is impossible to debug or even attempt trial and error diagnostics.

Error: Package systemd is not installed

I am trying to add wsddn to my Dockerfile based on Debian Trixie.

I get the following error:

11.45 Unpacking wsddn (1.8) ...
11.50 dpkg: dependency problems prevent configuration of wsddn:
11.50  wsddn depends on systemd; however:
11.50   Package systemd is not installed.
11.50
11.50 dpkg: error processing package wsddn (--install):
11.50  dependency problems - leaving unconfigured
11.50 Errors were encountered while processing:
11.50  wsddn

This is to be expected, because Debian containers have no systemd.

Is there another way to get just the static binary installed without the whole package?

Fails to install on Raspberry Pi (no armhf support?)

I tried to install on a Raspberry PI 3B using instructions
I seem to have an issue with the architecture armhf not being supported

WSDDN_MATCHING_DIST=`(source /etc/os-release; \
  mine=${UBUNTU_CODENAME:-${VERSION_CODENAME:-UNKNOWN}}; \
  supported=($(wget -qO- https://www.gershnik.com/apt-repo/conf/supported-dists.txt)); \
  if printf '%s\0' "${supported[@]}" | grep -Fxzq  -- "$mine"; then echo $mine; else echo ${supported[0]}; fi \
)`
> echo $WSDDN_MATCHING_DIST
bullseye
echo "deb" \
"[arch=$(dpkg --print-architecture)]" \
"https://www.gershnik.com/apt-repo/" \
"$WSDDN_MATCHING_DIST" \
"main" \
  | sudo tee /etc/apt/sources.list.d/wsddn.list >/dev/null
> cat  /etc/apt/sources.list.d/wsddn.list
deb [arch=armhf] https://www.gershnik.com/apt-repo/ bullseye main
> sudo apt update
Hit:1 http://archive.raspberrypi.org/debian bullseye InRelease
Get:2 http://mirror.ox.ac.uk/sites/archive.raspbian.org/archive/raspbian bullseye InRelease [15.0 kB]
Hit:3 https://packages.cisofy.com/community/lynis/deb stable InRelease
Hit:4 https://download.docker.com/linux/raspbian bullseye InRelease
Hit:5 https://mistertea.github.io/debian-et/debian-source buster InRelease
Get:6 https://www.gershnik.com/apt-repo bullseye InRelease [2,848 B]
Fetched 17.8 kB in 3s (6,644 B/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.
N: Skipping acquire of configured file 'main/binary-armhf/Packages' as repository 'https://www.gershnik.com/apt-repo bullseye InRelease' doesn't support architecture 'armhf’
uname -a
Linux pihole 6.1.21-v7+ #1642 SMP Mon Apr  3 17:20:52 BST 2023 armv7l GNU/Linux

[Feature Request]: Systemd socket support.

This looks great, thanks for building this.

I was wondering if you'd consider adding systemd socket support to this project?
Right now wsdd-native requries permissions to bind to sockets, and by using sd_listen_fds it would be possible to set the unit up with RestrictAddressFamilies=none.

Output in daemon mode is only sent to stdout, so I don't believe even AF_UNIX is necessary.

httpPath clarity

Hi I've been trying to get network discovery of a simple http server running on a single board computer (SBC) working on Windows and this looks like it will almost do what I want. I tried it out and it does make the SBC show up under the "Computer" section of the networking tab of File Explorer. What doesn't work, however, is double clicking the device. I'd like it to go to an address (either a fixed ip address or hostname.local address that avahi can resolve). I can't find a way to get that part configured. Currently, double clicking the SBC from the network tab gives an error that says:

"Windows cannot access \\the hostname I picked"

In the details dropdown it says "Error code: 0x80070035 The network path was not found."

I checked the source code and came across something that didn't make sense to me in config.h. It seems to me that httpPath ought to setting where double clicking the device goes but this is set to m_strUuid.

    auto endpointIdentifier() const -> const sys_string &   { return m_urnUuid; }
    auto httpPath() const -> const sys_string &             { return m_strUuid; }

To me the above m_strUuid doesn't seem like the right token to go there but I also don't really understand how all this works.

So I have two questions:

  1. Is there a way to configure which section a device will appear under? (IE not just "Computer")
  2. Is there a way to configure where double clicking the device will go?

Somme question to compare with wsdd2

Hello,

By reading https://github.com/Netgear/wsdd2 they specify:

WSD/LLMNR Discovery/Name Service Daemon

It looks like it also supports LLMNR discovery.
Isn't it the case for WSDD-native?
And what about this Name service daemon? Is it only a client part?
Or do they only specify more words which are also part of this project?

I consider trying WSDD-native as it looks like WSDD2 try to read /proc/sys/dev/boot/info which does not exist and I am asking myself it it does not cause some issues.

In another topic, could it be planned to add what NMBD from Samba provides? Because in the case of KSMBD, it would add a missing piece which complete all except if I miss-understand something.

Thanks.

Support ksmbd.mountd better versus expectation of samba being co-installed

Filing this issue in part as I've been migrating on my newest NAS refresh to a native ksmbd install where they've settled on (re)using the samba configuration file format for the foreseeable future with the user-space daemon ksmbd.mountd.

Would it be possible to add support to detect between samba vs ksmbd.mountd, and if ksmbd.mountd is detected checking /etc/ksmbd/ksmbd.conf for the settings? I think this would only minorly impact the Config::findSmbConf function to support?

One caveat is the ksmbd userspace tools do not support any security mode except 'user' and do not even support that key, so that key being missing is considered normal in the ksmbd configuration file.

[Debian 11] Fails installing "Some packages could not be installed"

Hello,

I followed the instructions to install it on Debian 11, but it fails with the following:

~# apt install wsddn
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 wsddn : Depends: libc6 (>= 2.34) but 2.31-13+deb11u5 is to be installed
         Depends: libstdc++6 (>= 11) but 10.2.1-6 is to be installed
E: Unable to correct problems, you have held broken packages.

Cheers,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.