0

I need to do port forwarding on my Linux (Debian 8) to intercept packets going through the machine.

It needs to be based on source IP, so different ports for different IPs.

I've though of using iptables ex.

iptables -t nat -A PREROUTING -s 10.1.10.78/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 10.1.10.31/32 -j REDIRECT --to-port 4444
iptables -t nat -A PREROUTING -s 10.1.10.79/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 10.1.10.21/32 -j REDIRECT --to-port 5000

But it seems going over 20K+ rules the machine becomes to slow, and iptables might need be the right solution. I now I can scale the machine up, but are there a better solution other than iptables for this "simple" challenge?

Alfred Balle
  • 409
  • 3
  • 9
  • 22
  • For a better performance you have to optimize your rules because having tens of thousands of iptables rules do need a lot of processing power. Try to setup rules using larger subnets if possible. For example if you need to forward both 10.1.10.78 and 10.1.10.79 to port 4321 then you could use a single 10.1.10.78/31 as source address instead of the two separate /32. – bcs78 Aug 06 '18 at 11:39
  • Unfortunately I need to allow my clients to set the port forwarding via an API. So larger subnets are quite difficult to archive. – Alfred Balle Aug 06 '18 at 11:55
  • Then it seems you won't get away without providing more processing power. – bcs78 Aug 06 '18 at 12:01
  • @AlfredBalle is your debian box getting slower while using it or is the port forwarding taking to long? – Kevin K. Aug 06 '18 at 12:19
  • These iptables rules are just a workaround for the lack of IPv6 anyway. In addition to this, make sure you have deployed IPv6 properly and that your end users have access to it. – Michael Hampton Aug 06 '18 at 13:13
  • @MichaelHampton I agree that IPv6 would make this problem obsolete but this question is explicitly about large scaled iptables. – Kevin K. Aug 06 '18 at 13:22
  • @KevinK. I'm well aware of what the question is about. – Michael Hampton Aug 06 '18 at 13:23
  • No offense @MichaelHampton. I just wanted to make sure the OP does not feel pushed away from his actual question. – Kevin K. Aug 06 '18 at 13:29
  • @KevinK. That's what "In addition to this" means. – Michael Hampton Aug 06 '18 at 13:30
  • Why would IPv6 make this obsolete? Wouldn't that simply make iptables need to route based on ipv6 instead of ipv4? The amount of rules would be the same? – Alfred Balle Aug 06 '18 at 13:35
  • @AlfredBalle You don't need ANY such rules with IPv6, because you would not have NAT or worse, large scale NAT. You would just route traffic normally. – Michael Hampton Aug 06 '18 at 14:30
  • Sounds like an X-Y problem. Nevertheless you might try using bpfilter (which will be in 4.18). See https://www.netronome.com/blog/bpf-ebpf-xdp-and-bpfilter-what-are-these-things-and-what-do-they-mean-enterprise/ – Mark Wagner Aug 06 '18 at 18:41
  • @michaelHampton But I'm not using it for NAT, but simply because I need to intercept all packets coming from my clients. But, I have to intercept ex. source IP1 on port 4321, source IP2 on port 8765, source IP3 on port 4321 etc. because I have different services running on each port (around 6 different ports my clients can be redirected to). – Alfred Balle Aug 06 '18 at 19:07
  • 1
    @AlfredBalle Your example doesn't reflect the various ports in use. It just tells many source ips, any protocol (is that tcp, udp, both etc...?) *any* destination port, all to port 4321. Can you [edit](https://serverfault.com/posts/925084/edit) to elaborate on the goal (the goal of the interception that is). Are you sure you need to redirect to a port? Is that some kind of semi-transparent proxy for example? Anyway can you include your comments and give more complete examples, because your previous comment (many ports) was really not expected reading your question. – A.B Aug 06 '18 at 22:19
  • Updated. Perhaps more clear yes. – Alfred Balle Aug 07 '18 at 09:42
  • I agree, it's looking more and more like an [XY problem](https://meta.stackexchange.com/q/66377/189912). – Michael Hampton Aug 07 '18 at 13:42

2 Answers2

3

I do not have an infrastructure at hand to simulate your scenario, but I think using custom iptables chains could help here. These could be utilized to cascade the rules and get away from a huge monolithic PREROUTING chain.

You need to think about how to assign the IP addresses to different chains first. In this little example, I will make use of IP subnets.

# Create custom chains
iptables -t nat -N chain-net-192.168.1.0/24
iptables -t nat -N chain-net-192.168.2.0/24
iptables -t nat -N chain-net-192.168.3.0/24

# Let appropriate connection jump to proper custom chains
iptables -t nat -A PREROUTING -s 192.168.1.0/255.255.255.0 -j chain-net-192.168.1.0/24
iptables -t nat -A PREROUTING -s 192.168.2.0/255.255.255.0 -j chain-net-192.168.2.0/24
iptables -t nat -A PREROUTING -s 192.168.3.0/255.255.255.0 -j chain-net-192.168.3.0/24

# Inside chain-net-192.168.1.0/24 perform actions
iptables -t nat -A PREROUTING -s 192.168.1.15/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 192.168.1.25/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 192.168.1.35/32 -j REDIRECT --to-port 4321

# Inside chain-net-192.168.2.0/24 perform actions
iptables -t nat -A PREROUTING -s 192.168.2.15/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 192.168.2.25/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 192.168.2.35/32 -j REDIRECT --to-port 4321

# Inside chain-net-192.168.3.0/24 perform actions
iptables -t nat -A PREROUTING -s 192.168.3.15/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 192.168.3.25/32 -j REDIRECT --to-port 4321
iptables -t nat -A PREROUTING -s 192.168.3.35/32 -j REDIRECT --to-port 4321

For further reference about custom iptables chains look at Linux Server Hacks at O'Reilly.

Kevin K.
  • 383
  • 1
  • 7
0

Maybe it is worth looking into nftables. It outperforms netfilter / iptables in many cases.

It is backported to debian 8 according to https://wiki.debian.org/nftables

eKKiM
  • 1,540
  • 9
  • 23