LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Security (https://www.linuxquestions.org/questions/linux-security-4/)
-   -   Programming iptables rules for 1:1 NAT (https://www.linuxquestions.org/questions/linux-security-4/programming-iptables-rules-for-1-1-nat-832662/)

jacques83 09-16-2010 04:30 PM

Programming iptables rules for 1:1 NAT
 
Hello all,

I am trying to program iptable rules for implementing a 1:1 NAT which does the following:

1. Forward all traffic from all ports on a public ip to a private ip
2. Forward traffic from a range of ports (x-->y) on a public ip, to a private ip

I did some google searches for the same, and came up with the following. I would appreciate it if someone could validate if this is indeed what I need to be doing.


iptables -A FORWARD -t filter -o eth0 -m state \
--state NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -A FORWARD -t filter -i eth0 -m state \
--state ESTABLISHED,RELATED -j ACCEPT

Thanks

AJ

nomb 09-16-2010 05:28 PM

This is pretty cool stuff and good info to learn; so I am going to take the 'teach a person to fish versus give them a fish' outlook.

If you are trying to use your Linux box as a gateway, which is what it sounds like, you are going to have to do a bit more.

Start looking at the 'nat' table, 'postrouting chain', 'masquerading', and 'ip forwarding'. <-- good google terms

howtoforge - nat_iptables <-- place to start

jacques83 09-16-2010 06:30 PM

Alright, I did some research, and came up with this:

Please note that the system has iptable rules already in place, so I need to add mine for 1:1 NAT and not worry about configuring VIFs.

iptables -t nat -A PREROUTING -i ${ext_interface} -d ${ext_ip} -j DNAT –to-destination ${int_ip}

iptables -t nat -A POSTROUTING -o ${ext_interface} -s ${int_ip} -j SNAT –to-source ${ext_ip}

Does anyone see any issues in this?

win32sux 09-16-2010 10:37 PM

Quote:

Originally Posted by jacques83 (Post 4099904)
Alright, I did some research, and came up with this:

Please note that the system has iptable rules already in place, so I need to add mine for 1:1 NAT and not worry about configuring VIFs.

iptables -t nat -A PREROUTING -i ${ext_interface} -d ${ext_ip} -j DNAT –to-destination ${int_ip}

iptables -t nat -A POSTROUTING -o ${ext_interface} -s ${int_ip} -j SNAT –to-source ${ext_ip}

Does anyone see any issues in this?

Looks good to me. Regarding this, though:
Quote:

Originally Posted by jacques83 (Post 4099834)
iptables -A FORWARD -t filter -o eth0 -m state \
--state NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -A FORWARD -t filter -i eth0 -m state \
--state ESTABLISHED,RELATED -j ACCEPT

I think it's a bad idea to allow all outbound packets in state NEW. That is, unless that's your intention. Are these forwarded packets going to a client or a server? Or perhaps a client that will be running certain daemons? I'd start out with something like this (example):
Code:


iptables -P FORWARD DROP

iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i ${ext_interface} -o ${int_interface} -d ${int_ip} \
-p TCP --dport 5700:6890 -m state --state NEW -j ACCEPT

iptables -A FORWARD -i ${int_interface} -o ${ext_interface} -s ${int_ip} \
-p TCP -m multiport --dports 443,80,21 -m state --state NEW -j ACCEPT

...then tighten/loosen the restrictions as desired. In this example ports 5700-6890/TCP are forwarded to the internal host, while said host is only allowed to start outbound connections to the standard HTTPS, HTTP, and FTP ports.

Just my :twocents:.

jacques83 09-17-2010 11:50 AM

I am a bit confused now ...

For my 1:1 NAT feature, should I be using the PREROUTING/POSTROUTING sample I posted, or use the original FORWARD sample?

win32sux 09-17-2010 03:54 PM

Quote:

Originally Posted by jacques83 (Post 4100830)
I am a bit confused now ...

For my 1:1 NAT feature, should I be using the PREROUTING/POSTROUTING sample I posted, or use the original FORWARD sample?

You need both. Your PRE/POSTROUTING looks good, but your FORWARD needs work. I just re-read your post and it seems you're working with two different external IPs. Is that correct? Please elaborate. Also, please explain what outbound packet restrictions you want.

jacques83 09-17-2010 04:23 PM

I am working with only "one" external IP. Essentially, I want to achieve the following ...

1. Have rules in my router, which forward all traffic from my public ip (from all ports), to a private ip which is hidden to the external world (but visible to my router)

2. Have rules in my router, which forward traffic from "specific port range" for my public ip, to a private up which is hidden to the external world (but visible to my router)

I do not think I have any restrictions for the outbound packets, except that all public ips should be pingable from this private ip via my router.

Also, when I try and program the prerouting/postrouting part, I do not see the rules in my iptables. Is there any step I miss here?

win32sux 09-17-2010 05:43 PM

Quote:

Originally Posted by jacques83 (Post 4101052)
I am working with only "one" external IP. Essentially, I want to achieve the following ...

1. Have rules in my router, which forward all traffic from my public ip (from all ports), to a private ip which is hidden to the external world (but visible to my router)

2. Have rules in my router, which forward traffic from "specific port range" for my public ip, to a private up which is hidden to the external world (but visible to my router)

Okay, but these two requirements aren't compatible. I mean, if you only want to forward a "specific port range", then you aren't gonna be forwarding "all traffic from my public ip (from all ports)". That's why it sounds like you've got more than one external IP. So if you only have one, you need to decide which of the above you want to achieve.

Quote:

I do not think I have any restrictions for the outbound packets, except that all public ips should be pingable from this private ip via my router.
Okay. After your next reply I think we should be able to offer you some iptables commands.

Quote:

Also, when I try and program the prerouting/postrouting part, I do not see the rules in my iptables. Is there any step I miss here?
Are you specifying that you wish to see the NAT table? Example:
Code:

iptables -nvL -t nat

jacques83 09-17-2010 10:07 PM

Ok, I am sorry I was not clear, but I provide an option to the user to either give me a port range and a source and destination ip, or just a source and destination ip. Both these count towards my 1-1 NAT user-cases. These are 2 separate cases based on what the user decides to do.

I agree that it might not be possible to do this in 1 command, but I can have branching in my code to make separate calls for either case. How would I go about programming my rules, given this information?

win32sux 09-17-2010 11:24 PM

Quote:

Originally Posted by jacques83 (Post 4101251)
Ok, I am sorry I was not clear, but I provide an option to the user to either give me a port range and a source and destination ip, or just a source and destination ip. Both these count towards my 1-1 NAT user-cases. These are 2 separate cases based on what the user decides to do.

OIC, yeah, that makes sense now. :)

Quote:

I agree that it might not be possible to do this in 1 command, but I can have branching in my code to make separate calls for either case. How would I go about programming my rules, given this information?
For the first case, you could do:
Code:

iptables -t nat -A PREROUTING -i ${ext_interface} -d ${ext_ip} \
-j DNAT --to-destination ${int_ip}

iptables -t nat -A POSTROUTING -o ${ext_interface} -s ${int_ip} \
-j SNAT --to-source ${ext_ip}

iptables -P FORWARD DROP

iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i ${ext_interface} -o ${int_interface} -d ${int_ip} \
-m state --state NEW -j ACCEPT

iptables -A FORWARD -i ${int_interface} -o ${ext_interface} -s ${int_ip} \
-m state --state NEW -j ACCEPT

For the second case, you could do:
Code:

iptables -t nat -A PREROUTING -i ${ext_interface} -d ${ext_ip} \
-p TCP --dport ${start_port}:${end_port} \
-j DNAT --to-destination ${int_ip}

iptables -t nat -A POSTROUTING -o ${ext_interface} -s ${int_ip} \
-j SNAT --to-source ${ext_ip}

iptables -P FORWARD DROP

iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i ${ext_interface} -o ${int_interface} -d ${int_ip} \
-p TCP --dport ${start_port}:${end_port} -m state --state NEW -j ACCEPT

iptables -A FORWARD -i ${int_interface} -o ${ext_interface} -s ${int_ip} \
-m state --state NEW -j ACCEPT

In the second case, you might want to turn the protocol match into a variable also, in case you're letting the user select between TCP and UDP.

jacques83 09-20-2010 02:11 PM

Thanks a bunch for your help. I really appreciate it. I will try out these commands.

jacques83 09-20-2010 06:32 PM

Hi, I tried to program the iptable and then run a simple test of trying to ssh the guest vm (and the guest ip i have), via my public ip. (for thr 1-1 NAT case -- all ports)

eg. (public ip: 192.168.30.43 , guest Ip : 10.1.1.2, external if: eth2 internal if: eth1)

iptables -t nat -A PREROUTING -i eth2 -d $publicIp -j DNAT --to-destination $guestIp
iptables -t nat -A POSTROUTING -o $eth2 -s $guestIp -j SNAT --to-source $publicIp
iptables -P FORWARD DROP
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $eth2 -o $eth1 -d $guestIp -m state --state NEW -j ACCEPT
iptables -A FORWARD -i $eth1 -o $eth2 -s $guestIp -m state --state NEW -j ACCEPT

Then, I tried something like:

aj@aj-laptop:~$ ssh root@192.168.30.43
ssh: connect to host 192.168.30.43 port 22: Connection timed out
aj@aj-laptop:~$

I am not really sure as to how to go about debugging this issue. I assume if everything worked fine, I should have been able to ssh into the machine via it's guest ip (10.1.1.2), accessed via the public ip

win32sux 09-20-2010 07:49 PM

Are you sure you don't have any other (potentially conflicting) rules active? Maybe post the output of:
Code:

iptables -nvL --line-numbers
Code:

iptables -nvL -t nat --line-numbers
BTW, you can slap a LOG rule onto the end of the FORWARD chain to see if packets are being filtered there:
Code:

iptables -A FORWARD -j LOG --log-prefix "FORWARD DROP: "

jacques83 09-20-2010 08:33 PM

Re-running. Had used the wrong eth (1 instead of 0)

jacques83 09-20-2010 08:41 PM

Code:

iptables -t nat -A PREROUTING -i eth2 -d 192.168.30.41 -j DNAT --to-destination 10.1.1.2
iptables -t nat -A POSTROUTING -o eth2 -s 10.1.1.2 -j SNAT --to-source 192.168.30.41
iptables -P FORWARD DROP
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth2 -o eth0 -d 10.1.1.2 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o eth2 -s 10.1.1.2 -m state --state NEW -j ACCEPT

Code:

root@r-4-TEST:~# iptables -nvL --line-numbers
Chain INPUT (policy DROP 0 packets, 0 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1      857  130K NETWORK_STATS  all  --  *      *      0.0.0.0/0            0.0.0.0/0         
2        0    0 ACCEPT    all  --  eth0  *      0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
3      793  127K ACCEPT    all  --  eth1  *      0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
4        2  168 ACCEPT    all  --  eth2  *      0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
5      20  1716 ACCEPT    icmp --  *      *      0.0.0.0/0            0.0.0.0/0         
6      23  1424 ACCEPT    all  --  lo    *      0.0.0.0/0            0.0.0.0/0         
7        0    0 ACCEPT    udp  --  eth0  *      0.0.0.0/0            0.0.0.0/0          udp dpt:67
8        0    0 ACCEPT    udp  --  eth0  *      0.0.0.0/0            0.0.0.0/0          udp dpt:53
9      42  2520 ACCEPT    tcp  --  eth1  *      0.0.0.0/0            0.0.0.0/0          state NEW tcp dpt:3922
10      0    0 ACCEPT    tcp  --  eth0  *      0.0.0.0/0            0.0.0.0/0          state NEW tcp dpt:8080
11      0    0 ACCEPT    tcp  --  eth0  *      0.0.0.0/0            0.0.0.0/0          state NEW tcp dpt:80

Chain FORWARD (policy DROP 0 packets, 0 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1        3  180 NETWORK_STATS  all  --  *      *      0.0.0.0/0            0.0.0.0/0         
2        0    0 ACCEPT    all  --  eth0  eth1    0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
3        0    0 ACCEPT    all  --  eth0  eth2    0.0.0.0/0            0.0.0.0/0         
4        0    0 ACCEPT    all  --  eth2  eth0    0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
5        0    0 ACCEPT    all  --  *      *      0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
6        3  180 ACCEPT    all  --  eth2  eth0    0.0.0.0/0            10.1.1.2            state NEW
7        0    0 ACCEPT    all  --  eth0  eth2    10.1.1.2            0.0.0.0/0          state NEW

Chain OUTPUT (policy ACCEPT 17 packets, 4848 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1      778  135K NETWORK_STATS  all  --  *      *      0.0.0.0/0            0.0.0.0/0         

Chain NETWORK_STATS (3 references)
num  pkts bytes target    prot opt in    out    source              destination       
1        0    0            all  --  eth0  eth2    0.0.0.0/0            0.0.0.0/0         
2        3  180            all  --  eth2  eth0    0.0.0.0/0            0.0.0.0/0         
3        0    0            tcp  --  !eth0  eth2    0.0.0.0/0            0.0.0.0/0         
4        9  540            tcp  --  eth2  !eth0  0.0.0.0/0            0.0.0.0/0

Code:

root@r-4-TEST:~# iptables -nvL -t nat --line-numbers
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1        1    60 DNAT      all  --  eth2  *      0.0.0.0/0            192.168.30.41      to:10.1.1.2

Chain POSTROUTING (policy ACCEPT 1 packets, 60 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1        0    0 SNAT      all  --  *      eth2    0.0.0.0/0            0.0.0.0/0          to:192.168.30.45
2        0    0 SNAT      all  --  *      eth2    10.1.1.2            0.0.0.0/0          to:192.168.30.41

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
root@r-4-TEST:~#


jacques83 09-20-2010 08:42 PM

aj@aj-laptop:~$ ssh root@192.168.30.41
ssh: connect to host 192.168.30.41 port 22: No route to host
aj@aj-laptop:~$

win32sux 09-20-2010 09:39 PM

I've added CODE tags to your post in order to add readability.

Going forward, please use CODE tags on your own.

Quote:

Originally Posted by jacques83 (Post 4103909)
Code:

Chain FORWARD (policy DROP 0 packets, 0 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1        3  180 NETWORK_STATS  all  --  *      *      0.0.0.0/0            0.0.0.0/0         
2        0    0 ACCEPT    all  --  eth0  eth1    0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
3        0    0 ACCEPT    all  --  eth0  eth2    0.0.0.0/0            0.0.0.0/0         
4        0    0 ACCEPT    all  --  eth2  eth0    0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
5        0    0 ACCEPT    all  --  *      *      0.0.0.0/0            0.0.0.0/0          state RELATED,ESTABLISHED
6        3  180 ACCEPT    all  --  eth2  eth0    0.0.0.0/0            10.1.1.2            state NEW
7        0    0 ACCEPT    all  --  eth0  eth2    10.1.1.2            0.0.0.0/0          state NEW


Well, the policy isn't getting hit so that's good. The rule which allows the handshake to start is getting hit, which is good too. No packets in state ESTABLISHED seem to be passing through here, though, which is bad.

Quote:

Code:

root@r-4-TEST:~# iptables -nvL -t nat --line-numbers
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1        1    60 DNAT      all  --  eth2  *      0.0.0.0/0            192.168.30.41      to:10.1.1.2

Chain POSTROUTING (policy ACCEPT 1 packets, 60 bytes)
num  pkts bytes target    prot opt in    out    source              destination       
1        0    0 SNAT      all  --  *      eth2    0.0.0.0/0            0.0.0.0/0          to:192.168.30.45
2        0    0 SNAT      all  --  *      eth2    10.1.1.2            0.0.0.0/0          to:192.168.30.41


The first POSTROUTING rule conflicts with the second one. That is, packets exiting eth2 will get their source address changed to 192.168.30.45, regardless (the 192.168.30.41 rule doesn't stand a chance). To fix that, just invert the rule order. But still, that doesn't seem to be the underlying cause of your issue, since neither rule is getting hit.

I must ask: Are you sure that the SSH box (10.1.1.2 AFAICT) is properly setup? It seems to me that having the gateway address on it improperly configured could cause these very symptoms. Let us know.

win32sux 09-21-2010 12:56 AM

Quote:

Originally Posted by jacques83 (Post 4103909)
Code:

1        3  180 NETWORK_STATS  all  --  *      *      0.0.0.0/0            0.0.0.0/0

BTW, have you tried killing this jump to check if the problem resides in NETWORK_STATS?
Code:

iptables -D FORWARD 1

jacques83 09-21-2010 05:07 PM

Thanks a lot for all your help. I was able to get this working finally. I was using an iso, and had some configuration issues for my vm (internal issues). After re-configuring my vm using a template, I was able to ssh from my public ip into the vm. This was the test case I tried to ensure the rules worked fine.


All times are GMT -5. The time now is 11:46 PM.