3

I would like to run an ftp server on a nixos host. I am using vsftpd, though could use something else if that would make a difference.

The ftp works fine on localhost, but the firewall is blocking me for remote usage. I have allowed TCP port 21, but that is not enough.

How should I configure the firewall to allow ftp connections (including writing to the ftp server)?

Here is the code that I currently have:

{
networking.firewall = { allowedTCPPorts = [ 20 21 ];
#                        connectionTrackingModules = [ "ftp" ];
                      };

  services.vsftpd = {
    enable = true;
#   cannot chroot && write
#    chrootlocalUser = true;
    writeEnable = true;
    localUsers = true;
    userlist = [ "martyn" "cam" ];
    userlistEnable = true;
  };
}

With the above, any use of ftp from off-host fails:

ftp> put dead.letter
200 PORT command successful. Consider using PASV.
425 Failed to establish connection.

Use of passive mode (e.g., with ftp -p) doesn't seem to help here:

ftp> put dead.letter
227 Entering Passive Mode (192,168,0,7,219,202).
ftp: connect: Connection timed out

Testing on a throwaway host with the firewall disabled

networking.firewall.enable = false;

Allows ftp -p to work; though of course turning off the firewall is not an attractive option.

Thanks for any help and pointers,

user3416536
  • 1,429
  • 9
  • 20
  • NixOS is used as a configuration management tool here, like [chef](https://stackoverflow.com/questions/tagged/chef) – Robert Hensing Jul 15 '19 at 13:56
  • The question is about using the Nix programming language to talk to the Nix module system, which is a library for expressing, combining and introspecting system configuration, among other things. – Robert Hensing Jul 15 '19 at 14:16
  • Thank you for the advice, I have added my current code to the question. – user3416536 Jul 15 '19 at 15:20
  • If you have a problem with active mode, then it's a local firewall that blocks the connection. Again, not a programming question. Or use a better FTP client, that supports the passive mode (all does, except for the Windows built-in `ftp`). – Martin Prikryl Jul 15 '19 at 15:32
  • Regrettably, passive mode doesn't work either (example added above) – user3416536 Jul 15 '19 at 16:24
  • For the passive mode to work, you have to allow passive ports on the server. – Martin Prikryl Jul 15 '19 at 19:55

2 Answers2

5

In passive mode the client will connect to the server with a second connection, that is used to transfer "things" (directory listings, files). In your case:

227 Entering Passive Mode (192,168,0,7,219,202)

The server requested the client to connect to it on port 219 * 256 + 202 = 56266.

This port is choosen by vsftpd dynamically and is not open in your firewall. You have to fix vsftpd to a fixed port for the passive connection and open this connection in the firewall.

vsftpd has two configuration options to set this: pasv_max_port and pasv_min_port. You should be able to set them in services.vsftpd.extraConfig. You probably want to open a small range of ports and open these in the firewall.

Matthias Wimmer
  • 3,789
  • 2
  • 22
  • 41
  • 1
    Bingo, thank you kindly for sharing this. For the record, I added `extraConfig = "pasv_min_port=56250\npasv_max_port=56260";` and `networking.firewall = { allowedTCPPortRanges = [ { from = 56250; to = 56260; } ]; };` to my configuration, that did the business. – user3416536 Sep 23 '19 at 11:04
4

To open ports in the firewall, use networking.firewall.allowedTCPPorts. For example:

networking.firewall.allowedTCPPorts = [ 21 ];
services.vsftpd.extraConfig = ''
  pasv_enable=Yes
  pasv_min_port=51000
  pasv_max_port=51999
'';
networking.firewall.allowedTCPPortRanges = [ { from = 51000; to = 51999; } ];

Firewall configuration is not automatic in NixOS, because that would defeat the purpose of having control over what traffic is allowed.

Some services have an openFirewall option to make this easier, but the vsftpd module does not seem to provide this convenience.

Edit: 20 is for the client. Only 21 needs to be opened. Edit: Plus a range for passive mode connections.

Robert Hensing
  • 6,708
  • 18
  • 23
  • Thank you @robert-hensing. Unfortunately, adding port 20 doesn't seem to resolve it. I've searched around for examples of other people doing the same thing, but have found nothing. – user3416536 Jul 15 '19 at 15:19
  • 1
    Port 20 is an incoming port (as of the local machine). It has to be enabled on the local machine, not on the server. – Martin Prikryl Jul 15 '19 at 15:32
  • Thank you. I have tried that (enabling port 20 on the client host, by setting networking.firewall.allowedTCPPorts, as above); still no dice. – user3416536 Jul 15 '19 at 16:35
  • How exactly did you do that? Can you even control local firewall with your nixos script? Show us the full script in the question. – Martin Prikryl Jul 15 '19 at 19:55
  • 1
    Are you starting transfers in active or passive mode. FTP needs two connections. The first connection is controll and uses port 21. The second connection uses different ports and depending on the mode gets started by the client or the server. I.e. in passive mode you have to open other ports on the server, in active mode you have to open ports on the client side. – Matthias Wimmer Jul 22 '19 at 06:48