LXD NAT Proxy Device and Port Forwarding

I’ve ran lxc config device add hyperhosted-demo server-port nat=true proxy listen=tcp:72.180.90.119:25590 connect=tcp:0.0.0.0:25590 after assigning a static IP to my container as other forum posts related to this subject have been solved with. 72.180.90.119 is the public IP address of my router. But I can only access the ip and port from the same computer with 72.180.90.119:25590, and trying with any computer on a different network does not work, and port check websites report the port as being closed.
I have verified that the port is allowed through the firewall and the host is in a DMZ on the router.
Any ideas what the problem is?

That 72 IP address is your public IP address. Is there an interface though on the host with that IP address? If not, use whichever IP address has the relevant network interface on the host.

There isn’t an interface for that since that’s the router IP, but I already tried setting listen to my internal IP address, and localhost with the same result. In the case of the internal IP, I could only access it on that computer with the internal IP and port, and same for localhost.
Here is the output for ifconfig:

enp39s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.48  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 2603:8081:1703:7200:722d:dfae:b27f:33f2  prefixlen 64  scopeid 0x0<global>
        inet6 2603:8081:1703:7200:e2ac:9a28:10fb:2af2  prefixlen 64  scopeid 0x0<global>
        inet6 2603:8081:1703:7200::1  prefixlen 128  scopeid 0x0<global>
        inet6 fe80::11be:387c:7bdc:5f9  prefixlen 64  scopeid 0x20<link>
        ether 2c:f0:5d:3f:8d:47  txqueuelen 1000  (Ethernet)
        RX packets 5272556  bytes 2626932834 (2.6 GB)
        RX errors 0  dropped 2837  overruns 0  frame 0
        TX packets 4777528  bytes 1398303441 (1.3 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 7373395  bytes 4176445204 (4.1 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7373395  bytes 4176445204 (4.1 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxdbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.145.245.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::216:3eff:fee5:91ea  prefixlen 64  scopeid 0x20<link>
        inet6 fd42:af13:a3ad:77c4::1  prefixlen 64  scopeid 0x0<global>
        ether 00:16:3e:e5:91:ea  txqueuelen 1000  (Ethernet)
        RX packets 3790931  bytes 248216964 (248.2 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2675590  bytes 957856207 (957.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth34fdf9ac: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether b2:e6:52:76:45:49  txqueuelen 1000  (Ethernet)
        RX packets 3165196  bytes 247759045 (247.7 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1915599  bytes 145707208 (145.7 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

And the output for lxc info hyperhosted-demo and lxc config show hyperhosted-demo:

justsnoopy30@main-computer:~$ lxc info hyperhosted-demo
Name: hyperhosted-demo
Location: none
Remote: unix://
Architecture: x86_64
Created: 2021/02/04 17:08 UTC
Status: Running
Type: container
Profiles: hosting-mini
Pid: 544806
Ips:
  lo:   inet    127.0.0.1
  lo:   inet6   ::1
  eth0:         inet    10.145.245.71   veth34fdf9ac
  eth0:         inet6   fd42:af13:a3ad:77c4:216:3eff:fee5:551b  veth34fdf9ac
  eth0:         inet6   fe80::216:3eff:fee5:551b        veth34fdf9ac
Resources:
  Processes: 45
  Disk usage:
    root: 1.03GB
  CPU usage:
    CPU usage (in seconds): 978
  Memory usage:
    Memory (current): 355.07MB
    Memory (peak): 1.28GB
  Network usage:
    eth0:
      Bytes received: 145.71MB
      Bytes sent: 247.76MB
      Packets received: 1915604
      Packets sent: 3165196
    lo:
      Bytes received: 23.68MB
      Bytes sent: 23.68MB
      Packets received: 355496
      Packets sent: 355496
justsnoopy30@main-computer:~$ lxc config show hyperhosted-demo
architecture: x86_64
config:
  image.architecture: amd64
  image.description: ubuntu 20.10 amd64 (release) (20210130)
  image.label: release
  image.os: ubuntu
  image.release: groovy
  image.serial: "20210130"
  image.type: squashfs
  image.version: "20.10"
  volatile.base_image: 5806d870eaa6833ecc596820b535c0e7d7716ec828365dd1e4ad19321a579f18
  volatile.eth0.host_name: veth34fdf9ac
  volatile.eth0.hwaddr: 00:16:3e:e5:55:1b
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Host
id":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid"
:1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"H
ostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.power: RUNNING
  volatile.uuid: f4c9a109-354b-4177-9e83-e1b5177b920c
devices:
  eth0:
    ipv4.address: 10.145.245.71
    ipv6.address: fd42:af13:a3ad:77c4:216:3eff:fee5:551b
    limits.egress: 8Mbit
    limits.ingress: 16Mbit
    name: eth0
    network: lxdbr0
    type: nic
  server-port:
    connect: tcp:0.0.0.0:25590
    listen: tcp:72.180.90.119:25590
    nat: "true"
    type: proxy
ephemeral: false
profiles:
- hosting-mini
stateful: false
description: ""

Proxy devices allow you to setup a socket listener on a specific IP and port(s) from the host and forward them into your container. However the listen IP must be setup and working on the LXD host first.

However the listen IP must be setup and working on the LXD host first.

What exactly do you mean by this? Can you give an example?

The output of ‘ip a’ on the host should show the IP in question is setup on the host.

This should have worked. Are you trying this in a public cloud or a private one?
GCE and Alicloud have the same networking feature, and that’s how it works.

You should also check any firewalls on the host or network aren’t blocking inbound traffic on your listen address or port.

Private network

Yeah I have checked and the port is allowed through the firewall.

My approach to this would be to setup tcpdump -nn -i <external interface> port <listen port> and check for traffic coming into the port on the external interface when you try to connect.

If you don’t see any then its some issue upstream of the host (or you haven’t configured the listen IP on the host). If you do see the traffic then its likely a local firewall blocking it to the proxy device.

So now I’m listening on 192.168.0.48 with port 25591, and I can connect with my internal ip 192.168.0.48. I did sudo tcpdump -nn -i lxdbr0 port 25591 and I see a lot of stuff show up. However when I did the same with the enp39s0 interface with tcpdump, nothing shows up.
First few lines of what I got when I used tcpdump on lxdbr0:

listening on lxdbr0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:23:05.133411 IP 10.145.245.71.25591 > 192.168.0.48.57500: Flags [P.], seq 1709968:1709982, ack 974, win 506, options [nop,nop,TS val 2133835740 ecr 1578524493], length 14

Now, when I try to connect with my public ip, 72.180.90.119, it times out. Nothing shows up on lxdbr0 with tcpdump now, but when I check on enp39s0 interface, I see this:

listening on enp39s0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:25:37.883072 IP 192.168.0.48.58102 > 72.180.90.119.25591: Flags [S], seq 3725773474, win 64240, options [mss 1460,sackOK,TS val 1795905890 ecr 0,nop,wscale 7], length 0
13:25:37.884992 IP 72.180.90.119.58102 > 192.168.0.48.25591: Flags [S], seq 3725773474, win 64240, options [mss 1460,sackOK,TS val 1795905890 ecr 0,nop,wscale 7], length 0
13:25:38.905755 IP 192.168.0.48.58102 > 72.180.90.119.25591: Flags [S], seq 3725773474, win 64240, options [mss 1460,sackOK,TS val 1795906913 ecr 0,nop,wscale 7], length 0

Lets not get lxdbr0 involved in the equation just yet.

First, you need to be connecting to your listen IP from a different machine. At the same time have tcpdump running on the interface of the listen IP.

If you don’t see anything then you don’t need to worry about lxdbr0, as the traffic isnt even getting to your host.

You say you can connect to the proxy by connecting to your internal IP 192.168.0.48, but you don’t say where you were connecting from for that test?

Do you see any traffic on your external interface when connecting externally to your external IP?
Again, lxdbr0 need not come in to it at this stage :slight_smile:

You say you can connect to the proxy by connecting to your internal IP 192.168.0.48, but you don’t say where you were connecting from for that test?

Ah yeah, sorry I meant I can connect with that on the same machine.

Do you see any traffic on your external interface when connecting externally to your external IP?
Again, lxdbr0 need not come in to it at this stage :slight_smile:

Just tried from my phone on another network, yes actually.

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp39s0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:41:03.255165 IP 172.58.71.191.29106 > 192.168.0.48.25591: Flags [S], seq 3738850355, win 65535, options [mss 1334,sackOK,TS val 39174572 ecr 0,nop,wscale 8], length 0

OK great, so we can see it arriving at

192.168.0.48.25591

So that rules out a network level firewall.
So setting up your proxy device to listen on that IP and port should work, and you previously confirmed it does work but only connecting locally from lxd host.

So this means it is almost cetainly a software firewall of some kind on your lxd host. Can you show output of sudo iptables-save

*filter
:INPUT DROP [20894:2757627]
:FORWARD DROP [240:14400]
:OUTPUT ACCEPT [4828:1394751]
:ufw-before-logging-input - [0:0]
:ufw-before-logging-output - [0:0]
:ufw-before-logging-forward - [0:0]
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-after-input - [0:0]
:ufw-after-output - [0:0]
:ufw-after-forward - [0:0]
:ufw-after-logging-input - [0:0]
:ufw-after-logging-output - [0:0]
:ufw-after-logging-forward - [0:0]
:ufw-reject-input - [0:0]
:ufw-reject-output - [0:0]
:ufw-reject-forward - [0:0]
:ufw-track-input - [0:0]
:ufw-track-output - [0:0]
:ufw-track-forward - [0:0]
:ufw-logging-deny - [0:0]
:ufw-logging-allow - [0:0]
:ufw-skip-to-policy-input - [0:0]
:ufw-skip-to-policy-output - [0:0]
:ufw-skip-to-policy-forward - [0:0]
:ufw-not-local - [0:0]
:ufw-user-input - [0:0]
:ufw-user-output - [0:0]
:ufw-user-forward - [0:0]
:ufw-user-logging-input - [0:0]
:ufw-user-logging-output - [0:0]
:ufw-user-logging-forward - [0:0]
:ufw-user-limit - [0:0]
:ufw-user-limit-accept - [0:0]
:LIBVIRT_INP - [0:0]
:LIBVIRT_OUT - [0:0]
:LIBVIRT_FWO - [0:0]
:LIBVIRT_FWI - [0:0]
:LIBVIRT_FWX - [0:0]
-A INPUT -j LIBVIRT_INP
-A INPUT -j ufw-before-logging-input
-A INPUT -j ufw-before-input
-A INPUT -j ufw-after-input
-A INPUT -j ufw-after-logging-input
-A INPUT -j ufw-reject-input
-A INPUT -j ufw-track-input
-A FORWARD -j LIBVIRT_FWX
-A FORWARD -j LIBVIRT_FWI
-A FORWARD -j LIBVIRT_FWO
-A FORWARD -j ufw-before-logging-forward
-A FORWARD -j ufw-before-forward
-A FORWARD -j ufw-after-forward
-A FORWARD -j ufw-after-logging-forward
-A FORWARD -j ufw-reject-forward
-A FORWARD -j ufw-track-forward
-A OUTPUT -j LIBVIRT_OUT
-A OUTPUT -j ufw-before-logging-output
-A OUTPUT -j ufw-before-output
-A OUTPUT -j ufw-after-output
-A OUTPUT -j ufw-after-logging-output
-A OUTPUT -j ufw-reject-output
-A OUTPUT -j ufw-track-output
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
-A ufw-before-input -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-input -p udp -m udp --sport 67 --dport 68 -j ACCEPT
-A ufw-before-input -j ufw-not-local
-A ufw-before-input -d 224.0.0.251/32 -p udp -m udp --dport 5353 -j ACCEPT
-A ufw-before-input -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT
-A ufw-before-input -j ufw-user-input
-A ufw-before-output -o lo -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -j ufw-user-output
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-forward -j ufw-user-forward
-A ufw-after-input -p udp -m udp --dport 137 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 138 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 139 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 445 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 67 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 68 -j ufw-skip-to-policy-input
-A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input
-A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-after-logging-forward -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-track-output -p tcp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-track-output -p udp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-logging-deny -m conntrack --ctstate INVALID -m limit --limit 3/min --limit-burst 10 -j RETURN
-A ufw-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-logging-allow -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW ALLOW] "
-A ufw-skip-to-policy-input -j DROP
-A ufw-skip-to-policy-output -j ACCEPT
-A ufw-skip-to-policy-forward -j DROP
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
-A ufw-user-input -p tcp -m tcp --dport 22 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 25565 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 25565 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 80 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 443 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 8192 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 8192 -j ACCEPT
-A ufw-user-input -d 192.168.0.0/24 -i lxdbr0 -j DROP
-A ufw-user-input -i lxdbr0 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 25591 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 25591 -j ACCEPT
-A ufw-user-output -d 192.168.0.0/24 -o lxdbr0 -j DROP
-A ufw-user-forward -d 192.168.0.0/24 -i lxdbr0 -j DROP
-A ufw-user-forward -i lxdbr0 -j ACCEPT
-A ufw-user-limit -m limit --limit 3/min -j LOG --log-prefix "[UFW LIMIT BLOCK] "
-A ufw-user-limit -j REJECT --reject-with icmp-port-unreachable
-A ufw-user-limit-accept -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p tcp -m tcp --dport 68 -j ACCEPT
-A LIBVIRT_FWO -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A LIBVIRT_FWO -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A LIBVIRT_FWI -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A LIBVIRT_FWI -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A LIBVIRT_FWX -i virbr0 -o virbr0 -j ACCEPT
COMMIT
# Completed on Sun Feb  7 14:32:19 2021
# Generated by iptables-save v1.8.5 on Sun Feb  7 14:32:19 2021
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN
-A LIBVIRT_PRT -s 192.168.122.0/24 -d 255.255.255.255/32 -j RETURN
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
COMMIT
# Completed on Sun Feb  7 14:32:19 2021
# Generated by iptables-save v1.8.5 on Sun Feb  7 14:32:19 2021
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Sun Feb  7 14:32:19 2021

Sorry, I reposted this because the first time it did not send as a reply.

Can you try disabling your firewall, see if it works externally, if it does then you know where to focus your attention.

Oh, yep now it works after I run ufw disable to disable the firewall. So somehow ufw must be blocking the connection to the container for the port when accessed externally…

You are using port 25590 at the start of the post but the firewall rules you showed, do not mention this exact port. The firewall rules talk about a 25591.

Ah yes, sorry I forgot to mention but I switched to port 25591 since I ended up needing to run something on port 25590 on the host.