目的:
當客戶端訪問某一個服務器端口時,將流量轉發到另外一台服務器的某一個端口。
客戶端->轉發服務器->目的服務器->轉發服務器->客戶端
理論:
首先看一下iptables處理流程。
這些操作使是在轉發服務器上完成的。
數據包從網卡進入,首先會被PREROUTING這個內置的規則鏈處理。之后會進行路由判斷。如果目的地址是本機,則會走INPUT規則鏈,然后提交給本機程序處理;如果目的地不是本機地址,且開啟了轉發功能,則會經過FORWARD規則鏈,然后准備將數據包發出。本機要發出的數據包和經過FORWARD的數據包,會經過路由判斷,然后再經過POSTROUTING規則鏈,最后從網卡發出。這里的ethX和ethY 可以是同一個網卡。
為了能讓數據包轉發到目的地址,需要在第一個路由判斷之前將目的地址用DNAT改成目的服務器的地址,這樣數據包就不會提交給上層程序。然后在數據包出網卡之前,將遠來源地址改成轉發服務器的地址。這樣目的服務器返回時會返回給轉發服務器,轉發服務器會根據之前建立的映射表再返回給客戶端。需要注意的是我們應該打開ipv4時的轉發功能。
具體實現:
- 假設轉發服務器的地址192.168.1.20 。目的服務器的地址是 220.181.111.188 。在轉發服務器上把8080端口轉發到220.181.111.188的80端口。
- 打開ipv4時的轉發功能
- 編輯"/etc/sysctl.conf",將net.ipv4.ip_forward改成1
- sysctl -p
- 在PREROUTING上修改目的地址
- iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 220.181.111.188:80
- 在POSTROUTING上修改源地址
- iptables -t nat -A POSTROUTING -d 220.181.111.188 -p tcp --dport 80 -j SNAT --to 192.168.1.20
- 或者將用偽裝的方式
- iptables -t nat -A POSTROUTING -d 220.181.111.188 -p tcp --dport 80 -j MASQUERADE
- 為了防止在FORWARD上面被丟棄,添加規則允許通過。
- iptables -I FORWARD -d 220.181.111.188 -p tcp --dport 80 -j ACCEPT
- iptables -I FORWARD -s 220.181.111.188 -p tcp --sport 80 -j ACCEPT
- 現在就可以在客戶端上測試一下訪問 192.168.1.20:8080 就會訪問到 220.181.111.188:80
最后提供一段腳本:
#!/bin/bash -
#===============================================================================
#
# FILE: iptable_redirect_port.sh
#
# USAGE: ./iptable_redirect_port.sh PROTOCOL SERVER_PORT DHOST DPORT [-d]
#
# DESCRIPTION: Redirect traffic to another server.
#
# OPTIONS: ---
# REQUIREMENTS: ---
# BUGS: ---
# NOTES: ---
# AUTHOR: Zhang Guangtong <zhgt123@gmail.com>
# ORGANIZATION:
# CREATED: 2015年08月05日 10:07
# REVISION: ---
#===============================================================================# example:
#iptables -t nat -A PREROUTING -p tcp --dport 1111 -j DNAT --to-destination 192.168.1.10:8022
#iptables -t nat -A POSTROUTING -d 192.168.1.10 -p tcp --dport 8022 -j MASQUERADEredirect_port()
{
PROTOCOL=$1
SERVER_PORT=$2
DHOST=$3
DPORT=$4
iptables -t nat -A PREROUTING -p $PROTOCOL --dport $SERVER_PORT -j DNAT --to-destination $DHOST:$DPORT
iptables -I FORWARD -d $DHOST -p $PROTOCOL --dport $DPORT -j ACCEPT
iptables -I FORWARD -s $DHOST -p $PROTOCOL --sport $DPORT -j ACCEPT
iptables -t nat -A POSTROUTING -d $DHOST -p $PROTOCOL --dport $DPORT -j MASQUERADE
}
clean_redirect_port()
{
PROTOCOL=$1
SERVER_PORT=$2
DHOST=$3
DPORT=$4
iptables -t nat -D PREROUTING -p $PROTOCOL --dport $SERVER_PORT -j DNAT --to-destination $DHOST:$DPORT
iptables -D FORWARD -d $DHOST -p $PROTOCOL --dport $DPORT -j ACCEPT
iptables -D FORWARD -s $DHOST -p $PROTOCOL --sport $DPORT -j ACCEPT
iptables -t nat -D POSTROUTING -d $DHOST -p $PROTOCOL --dport $DPORT -j MASQUERADE
}
usage()
{
echo "Usage: $0 PROTOCOL SERVER_PORT DHOST DPORT [-d]"
echo ""
echo "example1:"
echo " $0 tcp 443 192.168.1.20 8043"
echo " Visit this host on port 443 equal vist 192.168.1.20:443"
echo "example2:"
echo " $0 tcp 443 192.168.1.20 8043 -d"
echo " Clean previous rules"
echo "Notes: please make sure net.ipv4.ip_forward=1 in /etc/sysctl.conf and run \"sysctl -p\" to apply changes"
}if [ $# -lt 4 ]; then
usage
exit
fi
if [ "$5" == "-d" ]; then
clean_redirect_port "$@"
else
redirect_port "$@"
fi
用法:
./iptable_redirect_port.sh 協議(tcp或udp) 轉發服務器端口 目的服務器IP 目的服務器端口
示例
將訪問轉發服務器上的443端口轉到192.168.1.20:8043
./iptable_redirect_port.sh tcp 443 192.168.1.20 8043
刪除剛才的規則:
./iptable_redirect_port.sh tcp 443 192.168.1.20 8043 -d
收工。