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

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.