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
MathieuR
  • 131
  • 6

1 Answers1

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.

MathieuR
  • 131
  • 6