1

I have some problem configuring an iptables NAT on CentOS 7. Currently client behind the NAT can reach the external IP but not the external network.

I followed this tutorial to set up my NAT, knowing it worked well on Gentoo and Arch :

http://www.revsys.com/writings/quicktips/nat.html

to schematize my problem :

  • eth0 (external) = 192.168.1.1/24
  • eth1 (internal) = 192.168.2.1/24

when I ping from 192.168.2.2 :

  • ping 192.168.1.1 : OK
  • ping 192.168.1.2 : NOK
  • ping 8.8.8.8 : NOK

Note that I also set up a port forwarding rule from 192.168.1.1:80 to 192.168.2.2:80. This work well, according to Wireshark my packets are successfully forwarded to 192.168.2.2. Then 192.168.2.2 reply but packet are dropped, so I see multiples TCP retransmission. There isn't any "host administratively prohibited" messages.

Here is dropwatch messages when I try to connect to 192.168.2.2:80 from the outside :

1 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at tcp_rcv_state_process+1b0 (0xffffffff815e5030)
1 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at tcp_rcv_state_process+1b0 (0xffffffff815e5030)
1 drops at ip_error+68 (0xffffffff815c47d8)
2 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at tcp_v4_do_rcv+80 (0xffffffff815ef160)
1 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at tcp_v4_do_rcv+80 (0xffffffff815ef160)
1 drops at ip_error+68 (0xffffffff815c47d8)
2 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at tcp_v4_do_rcv+80 (0xffffffff815ef160)
2 drops at ip_error+68 (0xffffffff815c47d8)
1 drops at tcp_v4_do_rcv+80 (0xffffffff815ef160)
1 drops at ip_error+68 (0xffffffff815c47d8)

Please does someone have an idea of what I did wrong ? Thanks you everyone.

EDIT :

-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth1 -o eth0 -j ACCEPT
-A FORWARD -d 192.168.2.2/32 -p tcp -m tcp --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

Chain PREROUTING (policy ACCEPT 1270 packets, 123K bytes)
 pkts bytes target     prot opt in     out     source               destination         
   30  1696 DNAT       tcp  --  eth0 any     anywhere             anywhere             tcp dpt:http to:192.168.2.2:80

Chain INPUT (policy ACCEPT 347 packets, 42272 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 6 packets, 431 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 30 packets, 1696 bytes)
 pkts bytes target     prot opt in     out     source               destination                                             
    6   431 MASQUERADE  all  --  any    eth0  anywhere             anywhere 

EDIT :

Yes IP forwarding is correctly set. When I ping from 192.168.2.2 to 192.168.1.2 I can't see any packet incoming with Wireshark on 192.168.1.2. Also I can't see any packet leaving from eth0 when using Wireshark.

Curiously, when I successfully ping 192.168.1.1 from 192.168.2.2 I can't see any ICMP packet incoming on eth0 too.

I think I must add something I didn't disclosed because I didn't found it to be relevant. In reality I'm trying to NAT a network bridge named br0 (my eth1 here) to the local LAN. My server 192.168.2.2 is in a container with a veth connected to the bridge.

I don't know if I should edit all my post to better reflect the situation. I thought my problem was purely an iptable mistake, but it seem something is wrong in the network stack, because I should see incoming ICMP packets when pinging 192.168.1.1.

When I said I already made this setup on Gentoo and Arch, it was with containers too, using LXC. Now I try to use systemd-nspawn. Selinux is set as permissive. Pinging 192.168.2.2 from my CentOS host is ok, forcing it to use eth0 doesn't work but it's the normal behavior.

routes host :

default via 192.168.1.254 dev eth0 proto static metric 100 
192.168.2.0/24 dev br0 proto kernel scope link src 192.168.2.1 
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.1 metric 100

routes container :

default via 192.168.2.1 dev host0 proto static 
192.168.2.0/24 dev host0 proto kernel scope link src 192.168.2.2
  • You should post your active firewall rules. You can find it out using iptables -S or iptables -L -n – Diamant Nov 6 '17 at 13:38
  • Hello, thanks you for your answer. I edited my question to add my iptables rules as asked. – MathieuR Nov 6 '17 at 13:59
1

Finally I found the solution after very much headache...

I was using systemd-networkd to setup my bridge. While net.ipv4.ip_forward was correctly set to 1 and I also set up net.ipv4.conf.all.forwarding to 1, it seem systemd-networkd didn't take my default into account while seeting up the bridge.

Si it ended that net.ipv4.conf.br0.forwarding was set to 0. I just set it to 1 and now it work.

For everyone who happen to have a similar problem, run this command :

sysctl -a | grep "\.forwarding" | grep ipv4

Ensure that all your interfaces have forwarding enabled.

Have a nice day.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.