SMB aka CIFS (common internet file system) is a ubiquitous file sharing mechanism, but unfortunately it is very insecure. All files are sent clear over the line, and if you don't config password encryption, even passwords are sent as cleartext.

There is currently no built-in encryption or security in the CIFS protocol, nor is there any available as an extension to Samba, so we'll have to resort to external methods.

One of the nicer ways to secure Samba is by using stunnel. This is a little tool which listens on a port on the client machine and forwards all data sent to that port to another port/machine, encrypted via (Open)SSL.

Contents

  1. Setting up the server
  2. Configure samba
  3. Configure stunnel
  4. Simple stunnel configuration for a secure samba setup
  5. Run stunnel
  6. Configuring your clients
  7. Unix clients
  8. Windows clients
  9. References

Setting up the server

Configure samba

You set up the server just as you would normally, as described in How to set up a Samba Server.

If you wish to allow only secure traffic, you can let it listen on localhost with the following statement in smb.conf:

# Only listen on loopback interface
socket address=127.0.0.1

Configure stunnel

You can install security/stunnel from ?pkgsrc. Then you can copy /usr/pkg/share/examples/stunnel/stunnel.conf-sample and modify it to your needs. The following will be sufficient if you only need the bare minimum to get a secure samba setup:

Simple stunnel configuration for a secure samba setup

# OpenSSL certificate
cert = /usr/pkg/etc/stunnel/stunnel.pem
# Run chrooted as nobody
chroot = /var/run/stunnel
setuid = nobody
setgid = nobody
# This file is created after chrooting
pid = /stunnel

# Accept connections on port 800, on any interface
[smb]
accept  = 0.0.0.0:800
# instead of port 139, port 445 will also work, unless you're using Mac OS X clients
connect = localhost:139

As you can see, you'll need an SSL certificate/key. This can be generated like this:

# openssl req -new -nodes -x509 -out stunnel/stunnel.pem -keyout /etc/stunnel/stunnel.pem

Run stunnel

Just add stunnel=yes to your /etc/rc.conf:

# echo "stunnel=yes" >> /etc/rc.conf
# /etc/rc.d/stunnel start

Warning: stunnel is very silent. Even if it gets an error it will just fail silently. Check with pgrep if it's running.

Configuring your clients

Unix clients

On a Unix client you simply install and run security/stunnel as described above. You'll need to swap the port numbers and put it in client mode. ie, your stunnel.conf should look like this:

client=yes; [smb] accept=localhost:139 connect=servername:800

This makes your client act as a samba server, to which you can connect. As soon as you connect to your machine, the data is encrypted and forwarded to servername. You can run stunnel from rc.conf just like on the server side.

Of course you can easily test it by connecting to localhost:

# smbclient -U yoda //localhost/myshare

Windows clients

Connecting a Windows client to samba over stunnel is a major hassle. Some background on why this is a problem is in order.

Apparently, when Windows is booted, the kernel binds a socket to port 445 on every real (this is important as we'll see later on) network interface. This means that no other process can ever bind this port. (try it, you'll get a "permission denied" message). This would mean we need to use another port for our fake "shared folder". Unfortunately, the Windows filemanager has no way to specify which port to use when you click "map network drive", so that's not an option.

Luckily for us, Windows has the following odd behaviour: When you click "map network drive" in the filemanager, it will first try to connect to port 445. When it finds no service listening there, it will try to fall back to port 139. Only when that has no service listening either, it will tell the user it couldn't connect. We will "abuse" this behaviour by tricking it into using this port.

Simply binding stunnel to port 139 is impossible, because of the Windows behaviour where it binds ports 139 and 445 on every interface, even if no actual files are being shared. It turns out that it doesn't do this on loopback network devices. To install one, follow this set of instructions:

  1. Open the "add hardware" wizard from the control panel.
  2. Wait for it to search in vain for new hardware.
  3. Tell it "yes, I've already connected my hardware" or the wizard will end...
  4. Pick "add a new device" from the bottom of the list.
  5. Don't let windows search for the hardware but choose it from a list ("Advanced").
  6. Pick the category "Network adapters".
  7. Choose "Microsoft loopback adapter".

When our new "hardware" is installed, you need to assign it an IP and disable NetBIOS activity on it:

  1. Open the "properties" dialog from the contextmenu in the "network connections" overview.
  2. Deselect all bindings except the TCP/IP ones. Typically you'll need to deselect "client for Microsoft networks" and "File and printer sharing".
  3. Select "TCP/IP", and then "settings" (or "properties")
  4. Choose any private network IP address you'll never see in any real network. (10.232.232.232 is a good example)
  5. Click "Advanced..."
  6. Choose the tab titled "WINS"
  7. Under "NetBIOS settings", click on "Disable NetBIOS over TCP/IP"

Finally, we can install stunnel (Windows binaries are available from ?1(http://www.stunnel.org). Put this in the stunnel.conf file:

client=yes [smb] accept=10.232.232.232:139 connect=servername:800

It is advisable to install the stunnel service so it will start on system boot, which means it will be (semi-)transparent to the user.

To connect to the server, just open up the "map network drive" dialog and enter \\10.232.232.232\sharename in the "computer name" box. To make this process a little more userfriendly, think up a hostname and stick it in \winnt\system32\drivers\etc\hosts (windows NT/XP) or \windows\hosts (Windows '9x). The format of this file is exactly like /etc/hosts on Unix.

References