Skip to contentSkip to conversation

connection refused from DNATted host

DISCUSSION Giovanni Biscuolo 1 participant 2 messages May 27, 2024 – May 28, 2024

lore
Share & tools
lore
#0 lore raw

Hello,

I'm not subscribed to this list, please keep me in the From:, thanks!

I'm a new nftables user and it's the first time I try to configure a DNAT rule to "expose" the email ports of a virtual machine on internet.

I'm using libvirt to define and run a guest (IPv4 192.168.133.9) inside my host, the guest gets network config via DHCP and is able to ping and curl on the internet, masquerading is running properly... AFAIU the swws-bridge network bridge is working fine.

I'm using this ruleset (from 'nft list ruleset') to do the DNAT of tcp port 110 from Internet to 192.168.133.9:100

--8<---------------cut here---------------start------------->8---

table ip filter {
        chain input_wan {
                icmp type echo-request limit rate 5/second accept
                icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
                icmpv6 type echo-request limit rate 5/second accept
                ip protocol . th dport vmap { tcp . 22 : accept, tcp . 53 : accept, udp . 53 : accept }
        }

        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related accept
                iifname vmap { "lo" : accept, "eno1" : jump input_wan, "swws-bridge" : accept }
        }

        chain forward {
                type filter hook forward priority filter; policy drop;
                ct state established,related accept
                iifname "swws-bridge" oifname "eno1" accept
                iifname "eno1" oifname "swws-bridge" ip daddr 192.168.133.9 tcp dport 110 accept
        }

        chain trace_chain {
                type filter hook prerouting priority raw - 1; policy accept;
                ip saddr 93.56.171.217 meta nftrace set 1
        }
}
table ip nat {
        chain postrouting {
                type nat hook postrouting priority srcnat; policy accept;
                ip saddr 192.168.133.0/24 oifname "eno1" masquerade
        }

        chain prerouting {
                type nat hook prerouting priority dstnat; policy accept;
                iifname "eno1" tcp dport 110 dnat to 192.168.133.9
        }
}

--8<---------------cut here---------------end--------------->8---

If from 93.56.171.217 I try to telnet I get:

--8<---------------cut here---------------start------------->8---

$: telnet 162.55.88.253 110
Trying 162.55.88.253...
telnet: Unable to connect to remote host: Connection refused

--8<---------------cut here---------------end--------------->8---

with this trace on the firewall host (using "nft monitor trace | grep 'dport 110'"):

--8<---------------cut here---------------start------------->8---

trace id ff699e27 ip filter trace_chain packet: iif "eno1" ether saddr b4:8a:5f:36:a3:0f ether daddr b4:2e:99:c5:cc:1c ip saddr 93.56.171.217 ip daddr 162.55.88.253 ip dscp cs0 ip ecn not-ect ip ttl 53 ip id 63915 ip length 60 tcp sport 26971 tcp dport 110 tcp flags == syn tcp window 64240 trace id ff699e27 ip nat prerouting packet: iif "eno1" ether saddr b4:8a:5f:36:a3:0f ether daddr b4:2e:99:c5:cc:1c ip saddr 93.56.171.217 ip daddr 162.55.88.253 ip dscp cs0 ip ecn not-ect ip ttl 53 ip id 63915 ip length 60 tcp sport 26971 tcp dport 110 tcp flags == syn tcp window 64240 trace id ff699e27 ip nat prerouting rule iifname "eno1" tcp dport 110 dnat to 192.168.133.9 (verdict accept)
trace id ff699e27 ip filter forward packet: iif "eno1" oif "swws-bridge" ether saddr b4:8a:5f:36:a3:0f ether daddr b4:2e:99:c5:cc:1c ip saddr 93.56.171.217 ip daddr 192.168.133.9 ip dscp cs0 ip ecn not-ect ip ttl 52 ip id 63915 ip length 60 tcp sport 26971 tcp dport 110 tcp flags == syn tcp window 64240 trace id ff699e27 ip filter forward rule iifname "eno1" oifname "swws-bridge" ip daddr 192.168.133.9 tcp dport 110 accept (verdict accept)

--8<---------------cut here---------------end--------------->8---

AFAIU the "ip nat prerouting" rule and the "ip filter forward" rule are working as expecten and the packet is accepted... but the connection is refused.

Please could you help me find out what I'm missing?

Happy hacking! Gio'

Signature · 4 lines
Giovanni Biscuolo

«Si può sperare
 Che il mondo torni a quote più normali».
#1 lore raw

Re: connection refused from DNATted host (libvirt guests!)

Hello,

I'm not subscribed to this list, please keep me in the From: when replying, thanks!

I've found a solution, I'm porting here hoping it could be useful to others.

I've also change a little bit the subject to include the important missing information about libvirt guests.

Giovanni Biscuolo <[email protected]> writes:

[...]

Quoted 2 lines

I'm using libvirt to define and run a guest (IPv4 192.168.133.9) inside my host

OK now I've understand that:

1. libvirt (still?!?) uses iptables and not nftables to define firewall rules (see [1])

2. iptables defined filters are _not_ visible via "nft" commands, at least not via 'nft list ruleset' I was using to look at rules. I was actually expecting a uniform interface to netfilter, but I see that even today we still have to manage netfilter via (at least?) two different interfaces.

3. when defining a network bridge with a forward "mode='nat'" parameter (the default) libvirt configures firewalling rules (via iptables) so that «inbound connections from other networks are all prohibited; all connections between guests on the same network, and to/from the host to the guests, are unrestricted and not NATed.» (see [2]

The solution I've adopted is to (re)define the libvirt created network bridge (swws-bridge in my case) using forward "mode='open'", so that «no firewall rules will be added for the network» (see [2]) by libvirt and I can manage all firewall rules via nftables alone. Once reconfigured swws-bridge I was able to remotely connect to my DNATted (and forwarded) ports on my guest machine.

Another solution could have been to configure some libvirt nwfilters via XML (see [3])... but no :-D

[...]

Happy hacking.

[1] https://libvirt.org/firewall.html#firewalld-and-the-virtual-network-driver
so libvirt can use firewalld backends but not nftables directly :-(

[2] https://libvirt.org/formatnetwork.html#connectivity

[3] https://libvirt.org/formatnwfilter.html

Signature · 4 lines
Giovanni Biscuolo

«Si può sperare
 Che il mondo torni a quote più normali».