Making sure that IP's "connected" to the containers gameserver proxy shows users real IP?

Thus far, I’ve been able to get the users IP address by using nginx as a reverse proxy just fine. But with one of the containers I’m only using it for a gaming server, and as such I am unable to rely on the reverse proxy features provided by nginx.

For all my containers (v4.1), I am using the default init profile setting. So all containers I create have their own IP auto assigned by LXC. I figured, if adjustments are required for the future, I can do so later on. The only command I ran thus far is the following:

lxc config device add container name proxy listen=tcp:0.0.0.0:7777 connect=tcp:127.0.0.1:7777 proxy_protocol=true

To forward the 7777 gameserver port so people can connect. Wasn’t too sure if the proxy protocol was really needed though. But whenever a person connects, it shows as:

: Server started
127.0.0.1:60010 is connecting…
127.0.0.1:60138 is connecting…

I’d really like that to show the users real IP address. I think? I have to use iptables? But I’m using UFW. I hope I can get some assistance with this. If you need any more information from me, feel free to ask.

Regards,
Skyrider

Proxy protocol requires support in the target service, if the service doesn’t know how to read the connection string to get the real IP, then it won’t work.

In this case using nat=true may be the best option, you’ll need to set a fixed IP on the container though and will need the listen to also use a specific IP.

Often I find online that the IP’s given to containers are not fixed and are always static.But in my experience, regardless how many times I restart the container and or system, the IP address is always the same. And I haven’t even given them a static IP address.

Whenever I attempt to include the nat=true, I get:

Error: Invalid devices: Device validation failed “”: The PROXY header can only be sent to tcp servers in non-nat mode

I assume I have to make some adjustments, but I’m not familiar yet as to how.

You need to unset the proxy_protocol=true bit to get that error out.

The IPs are semi-static in that dnsmasq tries its best to derive a stable IP from the MAC, but for the proxy device to work in nat mode, the container must have an ipv4.address entry on its network interface.

So picking up where we left off from IRC…

The proxy by default opens a new connection and then ‘proxies’ the actual packets from the original inbound connection to your LXD host to the new connection into your container.

This is why you lose the original source address.

As @stgraber mentioned there are two ways around this whilst still using the proxy device:

  1. If the application supports the PROXY protocol header then you can enable this on the proxy device by setting proxy_protocol=true, this will instruct the proxy device to add the special header to the connections containing the original source IP allowing the application to harvest the original source IP.
  2. If the application isn’t TCP or can’t support the PROXY protocol header then you can use the proxy’s NAT mode by setting nat=true on the proxy device. This actually switches to using iptables/nftables to setup a destination NAT (DNAT) rule on the host that forwards the original packets to the container, which allows the original source address to be maintained.

However with NAT mode, unlike the proxy mode, the port forwarding is using actual networking between the host and the container, and so requires that the container is accessible using a static IP address from the perspective of the LXD host.

In the default LXD configuration (which you indicate you are using) LXD sets up a private bridge on the host with a random private subnet. The containers then use DHCP to request a temporary IP address in that subnet.

Whilst the address that the container is allocated may appear static, this is because the allocation algorithm used tries to always give the same IP to the same MAC address. However if there are a lot of containers running this isn’t guaranteed. The risk when using proxy device in NAT mode is that the IP address you are forwarding packets to isn’t actually the container you intended. This is why we require that when using the proxy in NAT mode you set a static IP.

To set a static IP for a container you do this:

lxc start <container>
lxc ls <container>
# Find the IPv4 address that has been allocated dynamically from the output
lxc stop <container>
lxc config device override <container> eth0 ipv4.address=<dynamic IP from above>

What this does is assign the dynamically assigned IP as a static DHCP lease in LXD. This means that LXD’s DHCP server will no longer allocate that IP to other containers, and will always allocate it to the container’s current MAC address. No changes are required inside the container, it still continues to use DHCP to configure its address, its just that its guaranteed to always be assigned the same one.

This then allows proxy NAT mode to be enabled.

To enable proxy NAT mode do this:

lxc config device set <container> <proxy device name> nat=true listen=tcp:<lxd.host.ip>:7777 connect=tcp:0.0.0.0:7777
lxc start <container>

Note, in order for NAT mode to work, you have to specify a real IP on the LXD host for listen, you can’t specify ‘0.0.0.0’, so please use the LXD host’s public IP (or IP you want the game service to appear on that is local to the LXD host).

Also, because the packets are being forwarded using ‘real’ networking, you cannot specify ‘127.0.0.1’ as the connect address, as that is just pointing to the LXD host’s local loopback interface. Instead specify ‘0.0.0.0’ which translates to the container’s statically allocated IP address we setup above.

2 Likes

Thank you, really appreciate it. That worked perfectly!

1 Like

@tomp

I’m in a little of a pickle at the moment. The above worked perfectly for Terraria, but I’m afraid I’m having issues with it for Minecraft.

So, I’ve added the first proxy ports:

sudo lxc config device add minecraft 25565 proxy listen=tcp:0.0.0.0:25565 connect=tcp:127.0.0.1:25565

sudo lxc config device add minecraft 25575 proxy listen=tcp:0.0.0.0:25575 connect=tcp:127.0.0.1:25575

As expected, that works fine for me to connect to the server. But as you know, it lists all connected players as 127.0.0.1. Now when I add your device override:

lxc config device set minecraft 25565 nat=true listen=tcp:10.248.110.221:25565 connect=tcp:0.0.0.0:25565

lxc config device set minecraft 25575 nat=true listen=tcp:10.248.110.221:25575 connect=tcp:0.0.0.0:25575

I can no longer connect to the gameserver. Am I doing something wrong here?

“25565”:
connect: tcp:0.0.0.0:25565
listen: tcp:10.248.110.221:25565
nat: “true”
type: proxy
“25575”:
connect: tcp:0.0.0.0:25575
listen: tcp:10.248.110.221:25575
nat: “true”
type: proxy
eth0:
ipv4.address: 10.248.110.221
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: minecraft
type: disk
ssh:
connect: tcp:127.0.0.1:22
listen: tcp:0.0.0.0:2030
type: proxy

minecraft@minecraft:~$ netstat -l | grep 25565
tcp 0 0 minecraft.lxd:25565 0.0.0.0:* LISTEN
udp 0 0 minecraft.lxd:25565 0.0.0.0:*

1 Like

Using tcpdump, can you see packets arrive in your container on that port when you try to connect to the proxy?

tcpdump doesn’t show anything when I attempt to connect to the server. MC also says “Can’t connect to server”. It’s like the override changed something which is blocking the port forward.

iptables-save on host please

Within LXD or the actual “host” where the container is on?

Either way, inside the container:

root@minecraft:~# iptables-save

Generated by iptables-save v1.8.4 on Wed Jun 17 14:22:13 2020

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:ufw-after-forward - [0:0]
:ufw-after-input - [0:0]
:ufw-after-logging-forward - [0:0]
:ufw-after-logging-input - [0:0]
:ufw-after-logging-output - [0:0]
:ufw-after-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-before-input - [0:0]
:ufw-before-logging-forward - [0:0]
:ufw-before-logging-input - [0:0]
:ufw-before-logging-output - [0:0]
:ufw-before-output - [0:0]
:ufw-logging-allow - [0:0]
:ufw-logging-deny - [0:0]
:ufw-not-local - [0:0]
:ufw-reject-forward - [0:0]
:ufw-reject-input - [0:0]
:ufw-reject-output - [0:0]
:ufw-skip-to-policy-forward - [0:0]
:ufw-skip-to-policy-input - [0:0]
:ufw-skip-to-policy-output - [0:0]
:ufw-track-forward - [0:0]
:ufw-track-input - [0:0]
:ufw-track-output - [0:0]
:ufw-user-forward - [0:0]
:ufw-user-input - [0:0]
:ufw-user-limit - [0:0]
:ufw-user-limit-accept - [0:0]
:ufw-user-logging-forward - [0:0]
:ufw-user-logging-input - [0:0]
:ufw-user-logging-output - [0:0]
:ufw-user-output - [0:0]
-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 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 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-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-forward -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-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-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-logging-allow -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW ALLOW] "
-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-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-skip-to-policy-forward -j DROP
-A ufw-skip-to-policy-input -j DROP
-A ufw-skip-to-policy-output -j ACCEPT
-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-user-input -p tcp -m tcp --dport 22 -j ACCEPT
-A ufw-user-input -p udp -m udp --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 25575 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 25575 -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
COMMIT

Completed on Wed Jun 17 14:22:13 2020

And the main host.

Generated by iptables-save v1.8.4 on Wed Jun 17 16:23:25 2020

*nat
:PREROUTING ACCEPT [3027:201960]
:INPUT ACCEPT [2303:160287]
:OUTPUT ACCEPT [2115:190233]
:POSTROUTING ACCEPT [2115:190233]
-A PREROUTING -d 10.248.110.221/32 -p tcp -m tcp --dport 25575 -m comment --comment “generated for LXD container minecraft (25575)” -j DNAT --to-destination 10.248.110.221:25575
-A PREROUTING -d 10.248.110.221/32 -p tcp -m tcp --dport 25565 -m comment --comment “generated for LXD container minecraft (25565)” -j DNAT --to-destination 10.248.110.221:25565
-A OUTPUT -d 10.248.110.221/32 -p tcp -m tcp --dport 25575 -m comment --comment “generated for LXD container minecraft (25575)” -j DNAT --to-destination 10.248.110.221:25575
-A OUTPUT -d 10.248.110.221/32 -p tcp -m tcp --dport 25565 -m comment --comment “generated for LXD container minecraft (25565)” -j DNAT --to-destination 10.248.110.221:25565
-A POSTROUTING -s 10.248.110.221/32 -d 10.248.110.221/32 -p tcp -m tcp --dport 25575 -m comment --comment “generated for LXD container minecraft (25575)” -j MASQUERADE
-A POSTROUTING -s 10.248.110.221/32 -d 10.248.110.221/32 -p tcp -m tcp --dport 25565 -m comment --comment “generated for LXD container minecraft (25565)” -j MASQUERADE
-A POSTROUTING -s 10.248.110.0/24 ! -d 10.248.110.0/24 -m comment --comment “generated for LXD network lxdbr0” -j MASQUERADE
COMMIT

Completed on Wed Jun 17 16:23:25 2020

Generated by iptables-save v1.8.4 on Wed Jun 17 16:23:25 2020

*mangle
:PREROUTING ACCEPT [6823075:2762925853]
:INPUT ACCEPT [3434513:331133690]
:FORWARD ACCEPT [3388562:2431792163]
:OUTPUT ACCEPT [3390385:5031125520]
:POSTROUTING ACCEPT [6778947:7462917683]
-A POSTROUTING -o lxdbr0 -p udp -m udp --dport 68 -m comment --comment “generated for LXD network lxdbr0” -j CHECKSUM --checksum-fill
COMMIT

Completed on Wed Jun 17 16:23:25 2020

Generated by iptables-save v1.8.4 on Wed Jun 17 16:23:25 2020

*filter
:INPUT DROP [381:19676]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [37:3133]
:ufw-after-forward - [0:0]
:ufw-after-input - [0:0]
:ufw-after-logging-forward - [0:0]
:ufw-after-logging-input - [0:0]
:ufw-after-logging-output - [0:0]
:ufw-after-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-before-input - [0:0]
:ufw-before-logging-forward - [0:0]
:ufw-before-logging-input - [0:0]
:ufw-before-logging-output - [0:0]
:ufw-before-output - [0:0]
:ufw-logging-allow - [0:0]
:ufw-logging-deny - [0:0]
:ufw-not-local - [0:0]
:ufw-reject-forward - [0:0]
:ufw-reject-input - [0:0]
:ufw-reject-output - [0:0]
:ufw-skip-to-policy-forward - [0:0]
:ufw-skip-to-policy-input - [0:0]
:ufw-skip-to-policy-output - [0:0]
:ufw-track-forward - [0:0]
:ufw-track-input - [0:0]
:ufw-track-output - [0:0]
:ufw-user-forward - [0:0]
:ufw-user-input - [0:0]
:ufw-user-limit - [0:0]
:ufw-user-limit-accept - [0:0]
:ufw-user-logging-forward - [0:0]
:ufw-user-logging-input - [0:0]
:ufw-user-logging-output - [0:0]
:ufw-user-output - [0:0]
-A INPUT -i lxdbr0 -p tcp -m tcp --dport 53 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-A INPUT -i lxdbr0 -p udp -m udp --dport 53 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-A INPUT -i lxdbr0 -p udp -m udp --dport 67 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-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 -o lxdbr0 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-A FORWARD -i lxdbr0 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-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 -o lxdbr0 -p tcp -m tcp --sport 53 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-A OUTPUT -o lxdbr0 -p udp -m udp --sport 53 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-A OUTPUT -o lxdbr0 -p udp -m udp --sport 67 -m comment --comment “generated for LXD network lxdbr0” -j ACCEPT
-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-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-forward -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-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-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-logging-allow -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW ALLOW] "
-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-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-skip-to-policy-forward -j DROP
-A ufw-skip-to-policy-input -j DROP
-A ufw-skip-to-policy-output -j ACCEPT
-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-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 2001 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2001 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 22 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 22 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 7777 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 7777 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2007 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2007 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 1338 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 1338 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2004 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2004 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2010 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2010 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2011 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2011 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2008 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2008 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2002 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2002 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2020 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2020 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2003 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2003 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2030 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2030 -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 25575 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 25575 -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
COMMIT

The host means where LXD is running (not the container).

Can you ping 10.248.110.221 from the LXD host?

Can you telnet from LXD host to 10.248.110.221 port 25565?

PING 10.248.110.221 (10.248.110.221) 56(84) bytes of data.
64 bytes from 10.248.110.221: icmp_seq=1 ttl=64 time=0.141 ms
64 bytes from 10.248.110.221: icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from 10.248.110.221: icmp_seq=3 ttl=64 time=0.094 ms
64 bytes from 10.248.110.221: icmp_seq=4 ttl=64 time=0.097 ms

telnet 10.248.110.221 25565
Trying 10.248.110.221…
Connected to 10.248.110.221.
Escape character is ‘^]’.

When I check if the port is open on some random port checker website, it says:

Port 25565 is closed on mainipaddress.

If I only use:

lxc config device add minecraft 25565 proxy listen=tcp:0.0.0.0:25565 connect=tcp:127.0.0.1:25565

Without overriding, It says the port is open.

Oh I see the issue, you have defined the proxy’s listen IP as 10.248.110.221 which is the same IP as the container’s IP. But this IP can’t be reachable from your external network (as otherwise you wouldn’t need to use the proxy in the first place).

Please can you show the output of ip a from both the LXD host and the container.

Main host:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether da:69:58:6f:5f:4e brd ff:ff:ff:ff:ff:ff
inet 45.83.107.179/22 brd 45.83.107.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 2a03:4000:46:165:d869:58ff:fe6f:5f4e/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::d869:58ff:fe6f:5f4e/64 scope link
valid_lft forever preferred_lft forever
3: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 06:3e:cf:8e:fc:c2 brd ff:ff:ff:ff:ff:ff
inet 10.248.110.1/24 scope global lxdbr0
valid_lft forever preferred_lft forever
inet6 fd42:78f0:8cd8:9b63::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::78d3:e5ff:fe01:3f40/64 scope link
valid_lft forever preferred_lft forever
5: vethb0fedfb4@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 36:6d:31:6a:38:b7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
7: veth05d9954f@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether f2:e8:8e:11:ef:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1
9: veth442647cf@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 9e:e1:c7:c1:3e:5b brd ff:ff:ff:ff:ff:ff link-netnsid 2
11: vethbc64ab11@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether b2:56:ff:44:26:50 brd ff:ff:ff:ff:ff:ff link-netnsid 3
13: vethe21eae5a@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether ce:dd:b4:c0:64:df brd ff:ff:ff:ff:ff:ff link-netnsid 4
15: vetha53d9e9f@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether ca:1d:a5:d4:ac:ca brd ff:ff:ff:ff:ff:ff link-netnsid 5
17: veth07fd44d2@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether de:bc:f8:9f:c5:0a brd ff:ff:ff:ff:ff:ff link-netnsid 6
19: veth0abed128@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 5a:87:91:5c:84:b7 brd ff:ff:ff:ff:ff:ff link-netnsid 7
21: veth7322ccf6@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 42:aa:20:cc:86:e6 brd ff:ff:ff:ff:ff:ff link-netnsid 8
23: veth24dbc5d8@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 46:4e:6d:72:b4:81 brd ff:ff:ff:ff:ff:ff link-netnsid 9
25: veth840cb4fb@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 9e:26:11:a8:3d:3d brd ff:ff:ff:ff:ff:ff link-netnsid 10
27: veth6fd7d634@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 2a:8d:57:23:76:29 brd ff:ff:ff:ff:ff:ff link-netnsid 11
29: veth6b79df20@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 36:9f:d9:8b:50:81 brd ff:ff:ff:ff:ff:ff link-netnsid 12
31: vethecad5e25@if30: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 06:3e:cf:8e:fc:c2 brd ff:ff:ff:ff:ff:ff link-netnsid 13
33: veth9c58bcaf@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether fa:64:c6:7b:94:a5 brd ff:ff:ff:ff:ff:ff link-netnsid 14
35: veth3ebe39f6@if34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 72:b6:1a:c5:58:2d brd ff:ff:ff:ff:ff:ff link-netnsid 15
39: veth4671aabe@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether d2:74:06:ee:be:09 brd ff:ff:ff:ff:ff:ff link-netnsid 17
61: veth24198c12@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 72:35:e2:39:30:e8 brd ff:ff:ff:ff:ff:ff link-netnsid 19
63: veth65ffc143@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether aa:3c:b0:84:d0:0b brd ff:ff:ff:ff:ff:ff link-netnsid 20
81: veth97005398@if80: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
link/ether 4a:1c:60:30:1b:8a brd ff:ff:ff:ff:ff:ff link-netnsid 16

Container:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
80: eth0@if81: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:16:3e:20:cb:98 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.248.110.221/24 brd 10.248.110.255 scope global dynamic eth0
valid_lft 2816sec preferred_lft 2816sec
inet6 fd42:78f0:8cd8:9b63:216:3eff:fe20:cb98/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 3054sec preferred_lft 3054sec
inet6 fe80::216:3eff:fe20:cb98/64 scope link
valid_lft forever preferred_lft forever

Yeah so the proxy’s listen IP needs to be the IP you want to publish the service on. In this case it should be your LXD host’s external IP 45.83.107.179.

Haven’t tried it yet, but if I may ask. How come it worked for the Terraria server with:

listen=tcp:<lxd.host.ip>

How is it different? As they are both game servers for others to connect to.

hits wall

I assumed it was the IP of the LXD container, not the hosts IP… wow. Because you mentioned “lxd” as begin part, started to think about its whois. Wow… I’m stupid.

So lxd.host.ip is the IP of the LXD host, and 10.248.110.221 does not appear in the output of ip a on the LXD host, and thus cannot be a valid lxd.host.ip.

I also cannot see any other dnat entries from your iptables-save output above, suggesting your other proxy device is not operating in nat mode, and thus is listening on the wildcard address on your lxd host, and therefore is implicitly listening on 45.83.107.179.

Ya, I was stupid… I didn’t consider using the main hosts IP today. Ugh, I apologize. Really appreciate the replies on the matter.

1 Like