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 -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.

3 Answers 3


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.

  • A virtual IP address (or a second public one) could be assigned to the VPN server so clients that behave like this can reach services on the server via IPsec tunnel (depending on the use case it might also require assigning special DNS servers to the VPN clients so hostnames are resolved to that second IP address after connecting to the VPN).
    – ecdsa
    Commented Jul 26, 2021 at 16:28

IPSec forces protection of any traffic coming from the subnets on the other end. If you are using openswan for example, the rightsubnets (and sometimes leftsubnets) would indicate any communication coming from the other end, so that you can allow only traffic coming from those subnets.

If you have RW clients connecting from various IPs, there are plugins for ppp, such as the ip-up and ip-down script, which you could use to allow or disallow certain ports for certain IPs.

  • Thanks @Noam. I'm using strongswan for IPSEC. Yes clients are RW and can be connecting from anywhere in the world. I'll checkout ppp plugin. In general how to identify the IPs of the RW clients connected so that we can filter them?
    – Phani
    Commented Sep 18, 2014 at 13:54
  • Are you using IPSec/L2TP? If you do, the PPP daemon is involved and hence calls the PPP ip-up/down scripts. If however, you are using StrongSwan, it involves its own set of plugins: left|rightupdown = <path> Commented Sep 21, 2014 at 11:45

You need to attach an IPsec policy either to the socket (difficult) or globally.

IPsec duplicates part of the firewall logic here, in that it allows you to match packets against IP addresses and ports, and look up the desired IPsec policy.

For normal VPN setups, policies usually apply to "all traffic from this subnet to that subnet", but they can be finer grained, e.g.

require all traffic to my IP address port 80 from that other IP address to be encrypted
deny all other traffic to my IP address port 80

It is possible to have a policy without a security association, in which case the kernel will consult the IKE daemon to get one.

If the client changes IP address, you can generate the "require" policies from the IKE daemon and only configure the "deny" policy statically, with a priority that is lower than the generated rules.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .