Port forwarding does not work

I’m trying to redirect incoming TCP connections on port 113 to 127.0.0.1:10113 where my ident daemon is running. I have the following configuration:

boot.kernel.sysctl = { "net.ipv4.ip_forward" = true; };

networking = {
  domain = "tld";
  hostName = "myhost";
  networkmanager.enable = false;
  nameservers = [ "9.9.9.10" "149.112.112.10" ];
  firewall = {
    enable = true;
    allowedTCPPorts = [ 113 10113 ];
  };
  useDHCP = false;
  nat = {
    enable = true;
    internalInterfaces = [ "lo" ];
    externalInterface = "ens3";
    forwardPorts = [
      {
        sourcePort = 113;
        proto = "tcp";
        destination = "127.0.0.1:10113";
      }
      {
        sourcePort = 10113;
        proto = "tcp";
        destination = "127.0.0.1:10113";
      }
    ];
  };
};

systemd.network = {
  enable = true;
  networks = {
    "10-default" = {
      matchConfig.Name = "ens3";
      DHCP = "yes";
      linkConfig.RequiredForOnline = "routable";
    };
  };
};

When connecting on the same machine to localhost, everything is fine:

# nc -zv 127.0.0.1 113  
Connection to 127.0.0.1 113 port [tcp/ident] succeeded!
# nc -zv 127.0.0.1 10113    
Connection to 127.0.0.1 10113 port [tcp/netiq-endpoint] succeeded!

When connecting on the same machine to the public IP, weird things start to happen:

# nc -zv my.public.ip.address 113 
Connection to my.public.ip.address 113 port [tcp/ident] succeeded!
# nc -zv my.public.ip.address 10113 
nc: connect to my.public.ip.address port 10113 (tcp) failed: Connection refused

When connecting to the host over the internet:

# nc -zv my.public.ip.address 113     
nc: connect to my.public.ip.address port 113 (tcp) failed: Connection refused
# nc -zv my.public.ip.address 10113
(hangs)

I can send ident commands when connecting from the same host, but when connecting remotely I can not. What is wrong here?

Maybe it is only redirecting connections from localhost because you only specify sourcePort. Maybe you need sourceIP idk

@TinajaStyle do you mean networking.nat.internalIPs = ["127.0.0.1/24"];? I tried that, no difference.

how about:
https://search.nixos.org/options?channel=25.11&show=networking.nat.externalIP&query=networking.nat

By default, you can’t forward a port from an external interface to a local one. This is a Linux security restriction. It can be disabled with the net.ipv4.conf.*.route_localnet sysctl setting, but I don’t recommend it.

The easiest workaround is probably to make your destinations use your public IP instead of 127.0.0.1.

If you also want this port forwarding rule to work on your local machine, you need to use the loopbackIPs option. That option should contain any of the IPs you’ll want to use locally to reference this service from port 113 — so, both 127.0.0.1 and your public IP to make both of the examples you tried to run work. (I’m not sure why both nc -zv 127.0.0.1 113 and nc -zv 127.0.0.1 10113 worked for you if you’re only running one ident daemon on port 10113; I don’t think the former should have worked, if everything else was configured as shown.)

Finally, lose this:

It’s a no-op at best.

3 Likes

@rhendric Thank you! That’s exactly what was the issue! Making identd listen on 0.0.0.0 and doing this

forwardPorts = [{
  sourcePort = 113;
  proto = "tcp";
  destination = "${addressIpv4}:10113";
}];

where addressIpv4 is my public IP makes the forwarding work.

1 Like