A quick search will get you a full list of all the doom and gloom surrounding SMB1. Unfortunately, SMB1 is still the only protocol you can use to browse for network services on a Windows network. Or, is it?
Basically, I really really like to be able to click “Network” and see a list of all the file shares and printers and stuff on my personal LAN. I’ve been using it that way for danged near 30 years now. I can change…but I really don’t want to.
I’m not going to get into a full list of the reasons to do this. I started writing that…and realized I was just saying a bunch of things that you can easily search up for yourself on some other blog. I’m not a writer, and I’m not trying to keep you captured here to flash ads at you and monetize this. I’m just trying to quickly document something that I think might be helpful for you, or for future me.
So, the long and short of it, is that SMB1 allows you to “Browse” the resources on a network. It’s insecure, and was invented decades ago by people that were obviously prioritizing convenience over security. Other replacements have been invented and work well on other operating systems, but Windows is still dependent on SMB1 by default. I’m going to try to set my network up with some other protocol.
I have Macs, Linux boxes, and Windows machines on my LAN. I need something that will work with all of those.
Enter DNS-SD
DNS-SD is a standard method that allows you to advertise network services using normal DNS records that can be placed on any DNS server. The official information is here: http://www.dns-sd.org/
Here’s how it works:
- For each service you want to advertise, you create a PTR record on your DNS server in this standard format:
<service_name>.<protocol> PTR <name of the resource>.<service_name>.<protocol>
- Create SRV record(s) with the name of the server(s) that can serve up the resource in this format:
<name of the resource>.<service_name>.<protocol> SRV 0 0 <port-number> <server-name>
- Add a TXT record, if needed, with additional information. The format depends upon the service being advertised.
For example, let’s say I want to advertise a “Welcome Fiends!” page on my web server called “booyah”. The page is at http://booyah.example.com/welcome.html
Not using https, so it’s on port 80
Service description I would like to use is Welcome Fiends!
I have a DNS server available only to my local LAN. I don’t want to advertise this to the world, but if there was some reason I wanted to advertise services to the whole world, I could do so by simply putting these records on a publicly visible DNS server!
My private DNS server is already set up for android606.com so, I add the following records:
_http._tcp PTR Welcome\ Fiends!._http._tcp
Welcome\ Fiends!._http._tcp SRV 0 0 80 booyah
TXT path=/welcome.html
(Note that the spaces have to be escaped with a backslash)
Now, I can hop on the local command line and test this using dig to get the new records.
First, get a list of all the HTTP pages advertised on the domain:
% dig PTR _http._tcp.example.com
;; ANSWER SECTION:
_http._tcp.android606.com. 3600 IN PTR Welcome\032Fiends!._http._tcp.android606.com.
Second, get a list of all the servers that can serve up the HTTP page we’re interested in:
% dig SRV Welcome\ Fiends!._http._tcp.android606.com.
;; ANSWER SECTION:
Welcome\032Fiends!._http._tcp.android606.com. 3600 IN SRV 0 0 80 booyah.android606.com.
;; ADDITIONAL SECTION:
booyah.android606.com. 3600 IN A 192.168.1.21
booyah.android606.com. 3600 IN AAAA fd00::21
Third, get the path to the document on the server:
% dig TXT Welcome\ Fiends!._http._tcp.android606.com.
;; ANSWER SECTION:
Welcome\032Fiends!._http._tcp.android606.com. 3600 IN TXT "path=/welcome.html"
Cool, so my DNS records are working!
Now, to make that “browseable”, you have to also put another service entry pointing back to the DNS server that basically means “Hey, everyone, this DNS server has public service records that you are free to browse.” Add these records to the DNS server:
b._dns-sd._udp IN PTR @ ; b = browse domain
lb._dns-sd._udp IN PTR @ ; lb = legacy browse domain
So, I open my macbook, open up a Finder window and click on “Network”. There’s a new entry there for my domain. A little “world” icon with android606.com next to it. I click the arrow to expand it, and then…
NOTHING. Why not?
So, I open up this other great program called Discovery (http://www.tildesoft.com/), which queries DNS-SD and displays the results. My new entry is totally there. Why isn’t it in Finder?
I guess Finder doesn’t display web servers. Aww….
So, I opened up Wireshark and took a look at the DNS requests sent out from my Mac. I can see the request for b._dns-sd._udp, followed by another one for db._dns-sd._udp, followed by a whole bunch of individual service requests. Looking at those, I’m assuming this is the full list of services supported by my version of Finder:
- _afpovertcp._tcp (Apple file sharing)
- _smb._tcp (SMB/Samba file sharing)
- _rfb._tcp (Remote framebuffer used by VNC)
- _adisk._tcp (Automatic disk discovery)
- _ipp._tcp (Internet printing protocol)
- _ipps._tcp (Not sure, guessing ipp + TLS?)
- _uscans._tcp (Don’t know, but I’m guessing this is for scanners?)
- _pdl-datastream._tcp (Printer page description language)
- _printer._tcp (LPR print spooler)
- _ptp._tcp (Picture transfer protocol)
- _scanner._tcp (Bonjour scanner)
I don’t know, some of those might be coming from iPhoto or something. Let’s try adding a record to the DNS for a file server, using one of those protocols. I looked up the _afpovertcp protocol in the dns-sd protocol list http://www.dns-sd.org/ServiceTypes.html (edit: The new-and-improved version of the service names list is here: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml) and see this protocol also has a path attribute in the TXT record. Then, a check with Apple’s ports list (https://support.apple.com/en-us/HT202944) tells us AFP uses port 548. So, these are the DNS records I added:
_afpovertcp._tcp PTR Fake\ File\ Share._http._tcp
Fake\ File\ Share._http._tcp SRV 0 0 548 www
TXT path=/
Check back in Finder… It worked! There’s a file share called Fake File Share listed now!
So, I’m a little bummed that I can’t make a web ‘service’ appear in the Finder, but this is a serious step towards my goal of browsing network shares without SMB1. I can advertise AFP and SMB file shares via DNS.
BUT, WHAT A PAIN.
I don’t want to edit my DNS zone files every time I want to share a folder. Nobody wants to wait for me to do that, either. Furthermore, most people reading this probably don’t even have a DNS server, and it’s honestly not exactly simple to set one up.
There’s a drop-in replacement though, and it’s designed to be automatic and fairly easy…
Enter mDNS
mDNS, or Multicast DNS, can serve up the same types of records as regular DNS, and all of the major OSes support it. As it sounds, it delivers DNS records, but it does it via multicast. This means any client on the local LAN segment can send a request via multicast, and then any machines on the local LAN segment will see the request and can respond to it.
“Zeroconf” (AKA Bonjour) uses mDNS to advertise DNS-SD records. Any machine that wants to share a resource can run an mDNS server, and then place a DNS-SD record for that resource on the server, using the special “.local” domain. For example, if I share a folder named FILEzz on my Mac named sliver, that will also create a record set like this on the Mac’s built-in mDNS server:
_smb._tcp PTR sliver._smb._tcp
sliver._smb._tcp SRV 0 0 445 sliver.local
TXT ""
So now, any other computer on the LAN can send out a Multicast DNS request for “_smb._tcp”, and this machine’s mDNS server will respond with a Multicast DNS reply including the PTR, SRV, and TXT records above.
If we’re okay with using .local instead of our ‘real’ domain, then this is easy to set up. If you are able to reach other computers on your network with <computername>.local, you already have it.
mDNS on MacOS
Comes set up out of the box. Woot! If you open a Terminal and do this:
dns-sd -V
You should get a message about a “running daemon” version, which means mDNS is up and running. That means you should be able to open Finder, go to Network, and see all the other computers on your network using mDNS to share stuff.
mDNS on Linux
May or may not be set up out of the box. It depends upon the distro you’ve got. I have a Raspberry Pi running Raspbian, and a couple Debian or Ubuntu boxes.
On Raspbian and Ubuntu, I just installed the avahi-daemon package with apt-get.
I also had to manually open port 5353 on my firewall by adding the following line to /etc/nftables.conf
udp dport 5353 accept
Now, I can ping raspy.local and ubuntu.local from my Mac. Yay.
mDNS on Windows
This is where things start to smell a little. I can’t get browsing for file servers via mDNS to work on Windows. Fortunately, there is some rudimentary mDNS support in Windows 10 and up- so at least I can access local machines using <servername>.local. For example, I can open a browser and go to http://cloud.local, or I can get a shell on my Raspberry Pi with ssh raspi.local
No browsing, though. Lame.
On older Windows machines, you can get this same functionality by downloading and installing Bonjour Print Services for Windows or iTunes from Apple.
A Browsing Kludge Miracle: WS-Discovery
There is one last thing to do to get Windows browsing working. Windows supports another service discovery protocol called WS-Discovery. I’m not sure exactly what Microsoft is planning to do with it, but there’s a daemon for Linux available.
Don’t get me wrong here- I don’t think WS-Discovery is a kludge, but I do think it feels kludgy to have to use it in addition to Zeroconf just to get browsing to work on Windows. It’s entirely too hard to get these software companies’ products to play nice with one another!
Anyway, here’s how I set it up:
On my Linux server with Samba shares, I use apt-get to install the wsdd package, enable the daemon, and then edit the config file with the following commands:
apt-get install wsdd
systemctl enable wsdd
Add firewall exceptions for nftables in /etc/nftables.conf:
# ws-discovery
udp dport 3702 accept
tcp dport 5357 accept
Customize the config file at /etc/default/wsdd as needed. By default, the daemon listens on all interfaces, and it gets all of it’s basic config from your Samba settings. The defaults work fine for me.
Start the service:
systemctl start wsdd.service
Awesome! Now, my file server is showing up in the Network browser on my Windows machines!
A binary version of wsdd is available for Mac OS, too. Download it directly from the author at https://github.com/gershnik/wsdd-native, and follow their install instructions.
After doing that, my Mac is visible from Windows as well. Not exactly plug-and-play, but I’ve achieved my goal: I’m able to get all of the computers in the house to browse to my Samba shares WITHOUT using SMB1! Awesome!