NuffStuff

IP forwarding

NAT uses IP forwarding and by default it’s not enabled in the kernel parameters. First we need to check if IP forwarding is enabled and if it’s not, we need to enable it.

To check if IP forwarding is enabled:

CentOS/RHEL:

1
2

jensd@cen~$sysctlnet.ipv4.ip_forward

net.ipv4.ip_forward=0

Debian:

1
2

jensd@deb~$sudosysctlnet.ipv4.ip_forward

net.ipv4.ip_forward=0

The above outputs shows that IP forwarding is not enabled.

To enable IP forwarding persistently (survives a reboot):

CentOS/RHEL:

1
2

jensd@cen~$echo «net.ipv4.ip_forward = 1″|sudo tee /etc/sysctl.d/99-ipforward.conf

net.ipv4.ip_forward=1

Debian:

1 jensd@deb~$sudosed -i’s/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g’etcsysctl.conf

To activate the changes immediately:

CentOS/RHEL:

1
2

jensd@cen~$sudosysctl -petcsysctl.d99-ipforward.conf

net.ipv4.ip_forward=1

Debian:

1
2

jensd@deb~$sudosysctl -p

net.ipv4.ip_forward=1

Theoretical explanation

To above scenario is better known as port forwarding and it allows you to forward an incoming packet to another destination. That destination can be another port or IP-address. With the scheme under here, I will try to make things a little more visual and explain how port forwarding works:

The left part of the scheme shows the original situation: the client connects to service A, running on server A (ip: 10.1.1.1). Incoming packets come through service A on server A and the outgoing packets go back to the original source IP, client A. The goal of the NAT-setup is to forward the traffic to service A running on server B (ip:10.2.2.2) without any modifications to client A. Our new setup needs to be transparent for the client.

The right part of the scheme shows our goal: the client still connects to TCP port 9999 to the IP of server A (10.1.1.1) so nothing changed on that side. As soon as a TCP packet with destination port 9999 arrives at server A, it should be forwarded to server B (ip: 10.2.2.2). Before redirecting the TCP-packet to the other machine, the packet needs to be modified so that it get’s sent back to server A before sending back to the original host.

To completely understand this process, we need to take a deeper look into how Iptables works. When a packet passes through Iptables, it passes a set of chains. Decisions made by those chains are called rules and that’s basically how you configure Iptables.

Overview of the chains used by Iptables

For our setup to work, we need to add a DNAT and SNAT rule (Prerouting and Postrouting). The first one will make sure that the packet gets routed to the other host (ip: 10.2.2.2) and the second one will make sure that the source address of the packet is no longer the original one but the one of the machine who performed the NAT. That way, the packet will be sent back to it’s original source via the host which owns ip 10.1.1.1.

Rule Creation

To create a new port-forwarding rule, select >> Firewall >> Firewall Rules and press the «New rule» button. Source and destination ports can only be defined for protocols that uses ports, i.e. TCP or UDP.

Step 1: Source

Define the source from which the service you are forwarding to is accessible. Usually, you do not need to specify anything other than the defaults. Where practical, limit the possible source(s) by selecting a host, group of hosts or specific network.

Choose the following to forward a WAN / RED port to a single internal server.

Standard Networks: Any or RED

Step 2: NAT

As this is a NAT rule, check «Use Network Address Translation (NAT)» and select «Destination NAT (Port forwarding)».

If you have public IP address space in the destination zone, you don’t need to check the NAT checkbox, but make sure to select ACCEPT as rule action further down below.

Choose the following to forward a WAN / RED port to a single internal server.

  • Use Network Address Translation(NAT)
  • Destination Nat(Port Forwarding)
  • Firewall Interface = Automatic

Step 3: Destination

Now, you will need to pick the server to which you are going to forward packets to. You can either select it from the dropdown boxes or enter the IP address directly. Note, that the system must be part of a local network that is reachable from the firewall.

Choose the following to forward a WAN / RED port to a single internal server.

Destination address (IP address or network) = Set to the address of the target computer/server.

Step 4: Protocol

You will want to pick one or more services that you will forward to the server you just choose, but never select «All» here.

Use a preset if you cannot remember the port number or select a protocol from the dropdown menu and enter the destination port you need. If you want to use a different port externally, you may enter it in «External port (NAT)» or leave it empty.

Choose the following to forward a WAN / RED port to a single internal server.

  • Choose a protocol, TCP, UDP are the most common.
  • Source port: = Blank, This is the port the client was using to talk to you.
  • Destination port: = The port the server is listening to.
  • External port (NAT): The port number the rest of the world will talk to, normally «Blank» for the same port as Destination port.

Step 5: Done

We are almost done, now. Just make sure that you select the «ACCEPT» option, so that all packets that match your rule are accepted by the firewall and don’t forget to add a descriptive remark.

Optionally, you may specify at which time the rule is active only. See Creating Firewall Rules (reference) for all about this feature.

Congratulations. You finally set up your port-forwarding!

Enable port forwarding

After going trough the above steps, we’re ready to active the port forwarding. As an example, I will forward the TCP port 9999 of host 192.168.202.103 to TCP port 80 on host 192.168.202.105.

First I will check that nothing is actually listening on port 9999 of host 192.168.202.103 by doing a telnet to port 9999 on that machine:

jensd@deb:~$ telnet 192.168.202.103 9999
Trying 192.168.202.103…
telnet: Unable to connect to remote host: Connection refused

To be sure that something is listening at port 80 of host 192.168.202.105, where I want to get forwarded, I can do the same check:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

jensd@test~$telnet192.168.202.10580

Trying192.168.202.105…

Connectedto192.168.202.105.

Escapecharacteris’^]’.

GETindex.htmlHTTP1.0
 

HTTP1.1200OK

DateThu,06Nov2014110049GMT

ServerApache2.2.22(Debian)

Last-ModifiedThu,06Nov2014104830GMT

ETag»563-b1-5072e6fe83634″

Accept-Rangesbytes

Content-Length177

VaryAccept-Encoding

Connectionclose

Content-Typetexthtml
 
html>body>h1>Itworks!h1>
p>Thisisthedefaultwebpageforthisserver.p>
p>Thewebserversoftwareisrunningbutnocontenthasbeenadded,yet.p>
body>html>

Connectionclosedbyforeignhost.

As you can see, there is a webserver running on port 80 on host 192.168.202.105.

Now, to forward port 9999 on host 192.168.202.103 to port 80 on host 192.168.202.105, we need to add the following rules to the iptables configuration of host 192.168.202.103:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

jensd@cen~$sudoiptables -tnat -APREROUTING -ptcp—dport9999 -jDNAT—to-destination192.168.202.10580

jensd@cen~$sudoiptables -tnat -APOSTROUTING -ptcp -d192.168.202.105—dport80 -jSNAT—to-source192.168.202.103

jensd@cen~$sudoiptables -tnat -L -n

ChainPREROUTING(policyACCEPT)

targetprotoptsourcedestination

DNATtcp—0.0.0.000.0.0.00tcpdpt9999to192.168.202.10580
 

ChainINPUT(policyACCEPT)

targetprotoptsourcedestination
 

ChainOUTPUT(policyACCEPT)

targetprotoptsourcedestination
 

ChainPOSTROUTING(policyACCEPT)

targetprotoptsourcedestination

SNATtcp—0.0.0.00192.168.202.105tcpdpt80to192.168.202.103

To test if my NAT-rule is working, I will repeat the test with telnet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

jensd@test~$telnet192.168.202.1039999

Trying192.168.202.103…

Connectedto192.168.202.103.

Escapecharacteris’^]’.

GETindex.htmlHTTP1.0
 

HTTP1.1200OK

DateThu,06Nov2014110307GMT

ServerApache2.2.22(Debian)

Last-ModifiedThu,06Nov2014104830GMT

ETag»563-b1-5072e6fe83634″

Accept-Rangesbytes

Content-Length177

VaryAccept-Encoding

Connectionclose

Content-Typetexthtml
 
html>body>h1>Itworks!h1>
p>Thisisthedefaultwebpageforthisserver.p>
p>Thewebserversoftwareisrunningbutnocontenthasbeenadded,yet.p>
body>html>

Connectionclosedbyforeignhost.

To permanently save the rules, execute iptables-save

CentOS/RHEL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

jensd@cen~$sudoiptables-save|sudoteeetcsysconfigiptables

#Generatedbyiptables-savev1.4.21onThuNov61202252014

*nat

:PREROUTINGACCEPT00

:INPUTACCEPT00

:OUTPUTACCEPT00

:POSTROUTINGACCEPT00

-APREROUTING -ptcp -mtcp—dport9999 -jDNAT—to-destination192.168.202.10580

-APOSTROUTING -d192.168.202.10532 -ptcp -mtcp—dport80 -jSNAT—to-source192.168.202.103
COMMIT

#CompletedonThuNov61202252014

#Generatedbyiptables-savev1.4.21onThuNov61202252014

*filter

:INPUTACCEPT86276022

:FORWARDACCEPT9811497

:OUTPUTACCEPT66684508

COMMIT

#CompletedonThuNov61202252014

Debian:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

jensd@deb~$sudoiptables-save|sudoteeetciptables.up.rules

#Generatedbyiptables-savev1.4.14onThuNov61207272014

*nat

:PREROUTINGACCEPT178

:INPUTACCEPT178

:OUTPUTACCEPT3159

:POSTROUTINGACCEPT3159

-APREROUTING -ptcp -mtcp—dport9999 -jDNAT—to-destination192.168.202.10380

-APOSTROUTING -d192.168.202.10332 -ptcp -mtcp—dport80 -jSNAT—to-source192.168.202.105
COMMIT

#CompletedonThuNov61207272014

#Generatedbyiptables-savev1.4.14onThuNov61207272014

*filter

:INPUTACCEPT44243400545

:FORWARDACCEPT145970

:OUTPUTACCEPT3185304340

COMMIT

#CompletedonThuNov61207272014

Iptables

The next thing to do is to check if Iptables is running on the system. Iptables is running as a kernel module so it can’t be seen as one of the normal processes.

CentOS/RHEL:

1 jensd@cen~$lsmod|grepiptable

Debain:

1
2
3
4
5
6
7
8

jensd@deb~$lsmod|grepiptable

iptable_nat129280

nf_nat182421iptable_nat

nf_conntrack_ipv4140783nf_nat,iptable_nat

nf_conntrack527203nf_conntrack_ipv4,nf_nat,iptable_nat

iptable_filter125360

ip_tables220422iptable_filter,iptable_nat

x_tables191183ip_tables,iptable_filter,iptable_nat

If there is no output, it means that Iptables isn’t loaded.

To start Iptables:

1
2
3
4

jensd@cen~$sudosystemctlstartiptables

jensd@cen~$lsmod|grepiptable

iptable_filter128101

ip_tables272391iptable_filter

Now that we are sure that Iptables is active on the system, we can check which rules are active.

For the INPUT, FORWARD and OUTPUT-chains:

1
2
3
4
5
6
7
8
9

jensd@cen~$sudoiptables -L -n

ChainINPUT(policyACCEPT)

targetprotoptsourcedestination
 

ChainFORWARD(policyACCEPT)

targetprotoptsourcedestination
 

ChainOUTPUT(policyACCEPT)

targetprotoptsourcedestination

For the NAT-related chains:

1
2
3
4
5
6
7
8
9
10
11
12

jensd@cen~$sudoiptables -tnat -L -n

ChainPREROUTING(policyACCEPT)

targetprotoptsourcedestination
 

ChainINPUT(policyACCEPT)

targetprotoptsourcedestination
 

ChainOUTPUT(policyACCEPT)

targetprotoptsourcedestination
 

ChainPOSTROUTING(policyACCEPT)

targetprotoptsourcedestination

As you can see, at this moment, no rules are configured and all traffic is allowed to and from the system without doing anything NAT-related.

In case you already have some rules configured, it’s a good idea (in a testing environment) to flush the current rules:

1
2

jensd@cen~$sudoiptables -F

jensd@cen~$sudoiptables -tnat -F

Ссылка на основную публикацию