Iptables – Allow only IPSEC outgoing traffic to a port (using IPTABLE?)

ipseciptablesnetworkingrouting

Problem:

I've a situation where IPSEC server and the target server (Say http server) happens to be the same machine and I need allow ONLY the traffic coming through IPSEC server to have access to a the port where my application is running and block everyone else on that port.

More details:

  • Setup looks like this: (Host A) <—-IPSEC VPN TUNNEL–> (Host B (Linux) where application running on port XXXX).
  • There is no additional IPSEC gateway or firewall involved.
  • Host B has public ip address(static).
  • Host A initiates the connection and VPN tunnel gets established.
  • When I logged the traffic coming to port XXXX after ipsec decryption, it looked like any normal packet and had src set to 'host A's ip address' and dst set to 'Host B's ip address' and since the packet is targeted to Host B, POSTROUTING rules wouldn't apply to it after ipsec processing.

For now, I've added rule in iptables to accept all traffic on port XXXX:

-A INPUT -p tcp –dport XXXX -s 0.0.0.0/0 -j ACCEPT

While this gets things moving, port XXXX is open to the world and that is dangerous.

Any idea how can I work it through ipsec configuration or iptables rules or in any other way to achieve the goal where ONLY traffic coming out of ipsec end point have access to XXXX ?

Few thoughts in my mind:

  • Is is possible to identify the TCP packets that leave the IPSEC end point and have a rule in iptables to allow only those packets to reach port XXXX ?
  • Is it possible to have some iptable/ipsec config to skip the INPUT rules after ipsec processing? this way I can have iptable rule to drop all packets to XXXX port and packets coming out of ipsec won't be affected.
  • May be create a virtual interface on host B and route IPSEC traffic through that and allow access to port XXXX only from that virtual interface?
  • Worst case, I will end up having ipsec server (Host B) and the application server (Host C) running on different machines and allow traffic to port XXXX on Host C ONLY from Host B.

I've tried the solution @With iptables, match packets arrived via IPSEC tunnel but it didn't work as I guess the mentioned policy applies to packets reaching to IPSEC, not for the packet that leaves IPSEC ?

Let me know if I've missed out any details or any additional information you need, Any help/suggestions would be greatly appreciated.

Best Answer

Thanks for the suggestions. It turned out to be related to how IPSEC VPN works on iOS (apple) devices.

On iOS devices, on turning the ipsec VPN ON, rule is added automatically in route table to send the IPSEC server/peer traffic directly to gateway to avoid looping (packet getting encrypted again) and rest of the traffic are sent to ipsec tunnel first to get encrypted and then onto ipsec server.

And in my case IPSEC server and the target server(where traffic is targeted) happens to be the same machine (resolves to same IP address), so when the traffic is sent to the target server (port XXXX), instead of its getting encrypted in IPSEC tunnel, it was sent directly to the server due to the special rule without getting encapsulated in ipsec packet. So when these packets arrived on server, it didn't get recognised as ipsec packets and that was the issue.

Since I couldn't avoid iOS client sending the traffic to port XXXX (though without ipsec encapsulation), I had to find a way to let only that device to have access to port XXXX and not to the whole world. So what I ended up doing was to have my own ipsec updown script on ipsec server that adds a INPUT chain rule dynamically to allow traffic from the established client's IP address to port XXXX on vpn connect and remove the rule on vpn disconnect. This way only the VPN connected clients will have access to port XXXX.

Related Topic