1

We have been using CSF on a virtualized (OpenVZ) environment successfully for a while combining venet and bridged interfaces so we can use public IPs + local addressed virtual systems.

Kernel IP routing table
Destination       Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.100        0.0.0.0         255.255.255.255 UH    0      0        0 venet0
xxx.xxx.xxx.24    0.0.0.0         255.255.255.255 UH    0      0        0 venet0
xxx.xxx.xxx.0     0.0.0.0         255.255.255.0   U     0      0        0 vmbr0
10.0.0.0          0.0.0.0         255.255.255.0   U     0      0        0 vmbr10
0.0.0.0           xxx.xxx.xxx.254 0.0.0.0         UG    0      0        0 vmbr0

We route traffic of "local" ips via an iptables rule:

iptables -t nat -A POSTROUTING -s "10.0.0.0/24" -o vmbr0 -j MASQUERADE

/proc/sys/net/ipv4/ip_forward value is obvioyly set to 1

The host and venet networked machines run their own CSF installation that creates all the firewall rules for this setup which includes the possibility to create "redirects" to internal IPs.

With this we can open specific ports on the host IP that are served by the local internal virtual machines on local based network. Among the long list of firewall rules that CSF creates are:

Chain PREROUTING (policy ACCEPT 53M packets, 15G bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 DNAT       tcp  --  !lo    *       0.0.0.0/0            XXX.XXX.XXX.184      tcp dpt:5100 to:10.0.0.100:5000 

Chain POSTROUTING (policy ACCEPT 9700K packets, 615M bytes)
num   pkts bytes target     prot opt in     out     source               destination         

3        0     0 SNAT       tcp  --  *      !lo     0.0.0.0/0            10.0.0.100          to:XXX.XXX.XXX.184 
8       10   600 MASQUERADE  all  --  *      vmbr0   10.0.0.0/24          0.0.0.0/0           

The redirect feature on CSF firewall works but the IP reported is the host one, not the originating IP so we can not limit it with another CSF instance (or simple firewall rule) on the destination virtual system. We understand that being on PREROUTING they can not be limited on on the host CSF either.

The CSF readme actually states "All redirections to another IP address will always appear on the destination server with the source of this server, not the originating IP address." so this is a standard feature.

CSF supports a postrules.sh file where we could include the NAT rules manually but we are unsure if with IPTABLES SNAT and/or DNAT it is possible to pass the "real" source IP to the destination of the NAT IP.

luison
  • 273
  • 1
  • 7
  • 21

2 Answers2

2

The only way to see the "real" source IP, you mentioned, at the destination is to avoid Natting or Masquerading it. Remember, SNAT and DNAT stand for Source and Destination Network TRANSLATION, respectively, so once the packet traverses the Natting rules, the source/destination addresses are "changed" for good. You can't retrieve them at the destination.

Daniel t.
  • 9,061
  • 1
  • 32
  • 36
1

Question:

We are unsure if with IPTABLES SNAT and/or DNAT it is possible to pass the "real" source IP to the destination.

Answer:

Yes, it is possible, and here's how to do it if you're using CSF. Don't rely on CSF's redirect feature, i.e. having a line similar to the following in /etc/csf/csf.redirect:

XXX.XXX.XXX.184|2222|10.0.0.100|22|tcp

Instead, put the following iptables commands in /etc/csf/csfpost.sh:

/sbin/iptables -I FORWARD -i vmbr0 -o vmbr10 -d 10.0.0.0/24 -j ACCEPT
/sbin/iptables -I FORWARD -i vmbr0 -o vmbr10 -d 10.0.0.0/24 -j LOCALINPUT
/sbin/iptables -t nat -A PREROUTING -i vmbr0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 10.0.0.100:22

Test:

$ ssh xxx.xxx.xxx.184 -p 2222 'netstat -tn'
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0     72 10.0.0.100:22           xxx.xxx.xxx.199:55812   ESTABLISHED

Explanation:

/sbin/iptables --table nat --append PREROUTING --in-interface vmbr0 --protocol tcp --match tcp --dport 2222 --jump DNAT --to-destination 10.0.0.100:22

This line redirects TCP traffic coming in on the external interface on port 2222 to the internal address 10.0.0.100 on port 22.

  • /sbin/iptables the full iptables executable is required.
  • --table nat working on the nat (Network Address Translation) table.
  • --append PREROUTING append this rule after all existing rules in the PREROUTING chain.
  • --in-interface vmbr0 catch all traffic comin in on the vmbr0 interface.
  • --protocol tcp catch only tcp traffic.
  • --match tcp use the tcp module.
  • --dport 2222 catch only traffic directed to port 2222.
  • --jump DNAT perform a Destination Network Address Translation.
  • --to-destination 10.0.0.100:22 change the destination address to 10.0.0.100 and the destination port to 22.
/sbin/iptables --insert FORWARD --in-interface vmbr0 --out-interface vmbr10 --destination 10.0.0.0/24 --jump LOCALINPUT

This line allows to not skip all of CSF's filtering just because we are redirecting.

  • /sbin/iptables the full iptables executable is required.
  • --insert FORWARD insert this rule before existing rules in the FORWARD chain. This is where redirected packets are going, as opposed e.g. to the INPUT chain.
  • --in-interface vmbr0 match traffic coming in on the vmbr0 interface.
  • --out-interface vmbr10 match traffic going out from the vmbr0 interface as an effect of redirection.
  • --destination 10.0.0.0/24 match only traffic destined to (redirected to) the internal network.
  • --jump LOCALINPUT go through the LOCALINPUT chain. This is where CSF performs all the good filtering it is known for, keeping banned and blacklisted IPs from reaching the system. With this rule, we extend CSF's filtering to all hosts on the internal network (as opposed to just traffic destined for the host where CSF is running).
/sbin/iptables --insert FORWARD --in-interface vmbr0 --out-interface vmbr10 --destination 10.0.0.0/24 --jump ACCEPT

This line passes all remaining forwarded traffic to the internal hosts.

  • /sbin/iptables the full iptables executable is required.
  • --insert FORWARD insert this rule before existing rules in the FORWARD chain. This rule will be evaluated after all the filering is performed in the LOCALINPUT chain.
  • --in-interface vmbr0 match traffic coming in on the vmbr0 interface.
  • --out-interface vmbr10 match traffic going out from the vmbr0 interface as an effect of redirection.
  • --destination 10.0.0.0/24 match only traffic destined to (redirected to) the internal network.
  • --jump ACCEPT after CSF has performed all its filtering (in the LOCALINPUT chain), we want remaining packets to be ACCEPTed.
simlev
  • 1,037
  • 2
  • 14
  • 22
  • Thanks. We were funny enough in the middle of reconfiguring a server and this seems to be working fine. We had some concerns that there might be a conflict with the masquerade rule to output local network traffic but so far so good. $IPT -t nat -A POSTROUTING -s "10.0.0.0/24" -o vmbr0 -j MASQUERADE – luison Aug 27 '20 at 14:18
  • 1
    @luison Glad it could help, seven years after you posted the question! Masquerading outgoing traffic is still needed, of course. – simlev Aug 28 '20 at 15:30