How can I forward the HTTP and SSH port to my internal server using iptables?

I do not have the router so I make the Linux system into a router having CentOS 6.4 fo forwarding the public network traffic to my local LAN. It has the two NIC cards. One for the public IP address (eth1) and another for the private IP address (eth2).

I have a server which is connected to my local LAN, suppose 192.168.1.2.

x.x.x.x is for the public IP address (this IP address is on eth1).

The Linux system router IP address suppose 192.168.1.1 (this IP address is on eth2).

I want that when someone from any network from anywhere use this, i.e.,

ssh x.x..x.x (public IP address) or using PuTTY

it will goes to server.

I disable the SELinux and iptables firewall on the server.

I did some Iptables modifications on the Linux system router, but it goes to itself which works as a router, not to the main server from the other network and the same network also.

iptables -t nat -A PREROUTING -p tcp -d 192.168.1.1 --dport 22 -j DNAT --to-destination 192.168.1.2:22

But it does not work.

And again I want to forward all the HTTP (80) traffic to my internal server using iptables from the same Linux system router.

What is the solution to this?


First of all make sure the packet forwarding is enabled in the kernel

# echo 1 > /proc/sys/net/ipv4/ip_forward

You can also make it permanent by adding below line to /etc/sysctl.conf

net.ipv4.ip_forward = 1

You have to do this on Linux Machine acting as a router. You can try the following rule on router machine.

iptables -t nat -A PREROUTING -i eth1 -d x.x.x.x -p tcp --dport 22 -j  DNAT --to-destination 192.168.1.2:22

Also let us know the output of your NAT Rules from the router box.

iptables -t nat -L -n -v

Based on this amazing DigitalOcean's tutorial about how to forward ports, I decided to re-write it here.

I spent many hours of research about how this works.. I'm new to linux and beginnings aren't always easy.. Here is example of my servers and it's port forwarding:

Firewall server (2 NIC cards) - network details:

  • Public IP address: xx.xx.xx.xx
  • Private IP address: yy.yy.yy.yy
  • Public interface: eth0
  • Private interface: eth1

Internal (e.g. ssh, web) server (1 NIC card) - network details:

  • Private IP address: zz.zz.zz.zz
  • Private interface: eth0

Solution:

Enable packet forwarding in kernel:

echo 1 > /proc/sys/net/ipv4/ip_forward

Define variables:

# Admin IP address (e.g. public home ip)
ADMIN="aa.aa.aa.aa"

# IP addresses of servers (e.g. in cloud):
FW_eth0_ip="xx.xx.xx.xx"
FW_eth1_ip="yy.yy.yy.yy"
WEB_eth0_ip="zz.zz.zz.zz"

# Services:
SSH="22"
HTTP="80"

Iptables port forwarding (with -m conntrack):

iptables -t nat -A PREROUTING -i eth0 -s $ADMIN -d $FW_eth0_ip -p tcp --dport $SSH -j DNAT --to-destination $WEB_eth0_ip
iptables -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport $SSH -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport $SSH -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -p tcp --sport $SSH -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -o eth1 -p tcp --dport $SSH -d $WEB_eth0_ip -j SNAT --to-source $FW_eth1_ip

Few notes:

  • "..-s $ADMIN -d $FW_eth0_ip.." (1st row) - added only for security reasons - it means that only ADMIN IP can access SSH (if not needed you can delete it)
  • -m conntrack is the same as -m state
  • I recommend to change default port of SSH to another port, like 1xxxx (in /etc/ssh/sshd_config)
  • check List of TCP and UDP port numbers
  • I use port 15xx1 to access SSH on Firewall server, and 15xxx2 the Internal

Terminal:

# access firewall server
$ ssh [email protected] -p 15xx1

# access internal server
$ ssh [email protected] -p 15xx2

More details about used rules are perfectly described in mentioned tutorial.

That's all from me, hope it will help you.