You're doing something strange. It is possible to do what you want, but you likely have a XY problem, i.e. this is not the root problem you're need to solve, but you're trying to fix a faulty solution to some other problem.
I suppose 3rd rule is your attempt to solve this problem.
Your 3rd rule works, it turns a packet (src=20.20.20.21:x dst=10.10.10.10:80)
into a packet (src=20.20.20.21:x dst=20.20.20.21:80)
, and then routes it towards new destination.
When packet reaches 20.20.20.21, it is immediately dropped, because reverse path filter considered this spoofing. Let's suppose it was accepted nevertheless, but to whom we reply? A packet was (src=20.20.20.21:x dst=20.20.20.21:80)
, so a reply will be (src=20.20.20.21:80 dst=20.20.20.21:x)
. Even if created, such reply packet will never leave web box to reach a NAT box and be translated back.
The resolution is to translate both destination and source for these packets, so the 20.20.20.21 will not see it's a packet from itself. Packet must be changed so reply will get routed back to the NAT box. It is possible to do with the following additional rule:
iptables -t nat -A POSTROUTING -s 20.20.20.21 -d 20.20.20.21 --dport 80 -j SNAT --to-source 10.10.10.10
Notes:
- it is doing a SNAT and therefore is in the POSTROUTING chain
- it matches packet by its destination address already translated with DNAT (your 3rd rule - it is still needed!)
- source address is changed to some address of NAT box. 20.20.20.20 in place of 10.10.10.10 also will work equally good.
The 20.20.20.21 will see this as a new packet (src=10.10.10.10:x dst=20.20.20.21:80), so it'll accept and a reply will properly reach the NAT box. Then NAT will replace both addresses back and return translated packet to web server box. So communication will succeed.
As I said, this is a very strange situation. While this will work, avoid it. Unusual firewall rules, hard to understand, inefficient design.
Why the 20.20.20.21 must coummunicate with itself via address it doesn't own, through another system? A DNS issue? You have some hostname
, for which some (outside) DNS server answers 10.10.10.10? Then you better make either internal DNS server which will answer 20.20.20.21 just for local network, or make 20.20.20.21 never do such DNS query and "just know" a hostname
is served by 20.20.20.21, by adding a line into its /etc/hosts
file. That solution is solid (some name is served by me? Then that name belongs to me); it is easy to understand. Also it will bypass network hardware and create less system load, and it will work much faster, because local packets skip many layers of network stack.
Last note: if that's really a complete firewall and filter FORWARD policy is ACCEPT (the default), your fourth rule does nothig. In either case better is to remove it. Even if it's not a complete firewall, last rule looks strange. To give better suggestions, I need to see a complete firewall (an output of iptables-save
).