系统环境 :
| 型号 | Dell Poweredge SC1425 |
|---|---|
| 内存 | 2G |
| CPU | Intel(R) Xeon(TM) CPU 2.80GHz x2 |
| eth0 | Intel Corporation 82541GI/PI Gigabit Ethernet Controller |
| eth1 | Intel Corporation 82541GI/PI Gigabit Ethernet Controller |
软件环境 :
| 操作系统 | CentOS4.6 |
|---|---|
| Kernel | 2.6.9-67.0.7.ELsmp |
| Iptables | iptables-1.2.11-3.1.RHEL4 |
目标 :使用iptables搭建一个基本的应用级网关防火墙,实现外网和内网的简单通信,实现一个简单的端口映射和ip/mac绑定的网关
# 以下内容摘自iptables manpage # iptables [-t table] -P chain target [options] # -P, --policy chain target # Set the policy for the chain to the given target. See the section TARGETS for the legal targets. # Only built-in (non-user-defined) chains can have policies, and neither built-in nor user-defined # chains can be policy targets. # 下面的代码摘自前面一节构建基础网关,设定默认允许所有链上的默认规则为允许 # 实际上这是一种Allow-all策略,后面我们会解释为什么选用这种策略 IPTABLES=/sbin/iptables $IPTABLES -P INPUT ACCEPT $IPTABLES -P FORWARD ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -t nat -P PREROUTING ACCEPT $IPTABLES -t nat -P POSTROUTING ACCEPT $IPTABLES -t nat -P OUTPUT ACCEPT # 对一台普通的服务器而言,以上的ACCEPT均可以简单的换成DROP,以实现Deny-all策略 # 这里不得不多说一句,我的前提是你很熟悉iptables机制或者这台服务器就在你的手边,可以直接本机登陆 # 否则假如你把规则指定成Deny-all,有没有开启对自己的允许,然后远程登录不上去了,可不要找我麻烦 :-)

# 执行下面的命令可以查看你的网关中NAT表情况
cat /proc/net/ip_conntrack
# 下面的命令帮你明确一下NAT表的规模
wc -l /proc/net/ip_conntrack
#或者
grep ip_conntrack /proc/slabinfo | awk '{print $1 ',' $2;}'
# 下面的命令帮你统计NAT表中占用端口最多的几个ip,很有可能这些家伙再做一些bt的事情,嗯bt的事情:-)
cat /proc/net/ip_conntrack | cut -d ' ' -f 10 | cut -d '=' -f 2 | sort | uniq -c | sort -nr | head -n 10# 实现网关的简单端口映射 # 具体功能:实现外网通过访问网关的外部ip:80,可以直接达到访问私有网络内的一台主机192.168.1.10:80效果 LOCAL_EX_IP=11.22.33.44 #设定网关的外网卡ip,对于多ip情况,参考《如何让你的Linux网关更强大》系列文章 LOCAL_IN_IP=192.168.1.1 #设定网关的内网卡ip INTERNAL="eth1" #设定内网卡 # 这一步开启ip转发支持,这是NAT实现的前提 echo 1 > /proc/sys/net/ipv4/ip_forward # 加载需要的ip模块,下面两个是ftp相关的模块,如果有其他特殊需求,也需要加进来 modprobe ip_conntrack_ftp modprobe ip_nat_ftp # 这一步实现目标地址指向网关外部ip:80的访问都吧目标地址改成192.168.1.10:80 iptables -t nat -A PREROUTING -d $LOCAL_EX_IP -p tcp --dport 80 -j DNAT --to 192.168.1.10 # 这一步实现把目标地址指向192.168.1.10:80的数据包的源地址改成网关自己的本地ip,这里是192.168.1.1 iptables -t nat -A POSTROUTING -d 192.168.1.10 -p tcp --dport 80 -j SNAT --to $LOCAL_IN_IP # 在FORWARD链上添加到192.168.1.10:80的允许,否则不能实现转发 iptables -A FORWARD -o $INTERNAL -d 192.168.1.10 -p tcp --dport 80 -j ACCEPT # 通过上面重要的三句话之后,实现的效果是,通过网关的外网ip:80访问,全部转发到内网的192.168.1.10:80端口,实现典型的端口映射 # 特别注意,所有被转发过的数据都是源地址是网关内网ip的数据包,所以192.168.1.10上看到的所有访问都好像是网关发过来的一样,而看不到外部ip # 一个重要的思想:数据包根据“从哪里来,回哪里去”的策略来走,所以不必担心回头数据的问题 # 现在还有一个问题,网关自己访问自己的外网ip:80,是不会被NAT到192.168.1.10的,这不是一个严重的问题,但让人很不爽,解决的方法如下: iptables -t nat -A OUTPUT -d $LOCAL_EX_IP -p tcp --dport 80 -j DNAT --to 192.168.1.10
#!/bin/sh
#=======================================
#===Author : yang.fang ===
#===Email : yangfang@fudan.edu.cn ===
#===MSN : yang.fang@adways.net ===
#===QQ : 78461151 ===
#=======================================
# Easy port mapping shell script
# Created by yangfang 2006.8.21
# Last modified by yangfang (2008.3.31)
# Change log
# 2006.8.21 yang.fang beta version. can do.
# 2007.5.11 yang.fang 0.1 version. use array to store LOCAL_EX_IPs.
# 2008.3.31 yang.fang 0.2 version. fix firewall itself can not reach port map server bug.
# 2008.3.31 yang.fang 0.3 version. cut the ALL type down, for it does no use. enable config check.
# base setting
IPTABLES=/sbin/iptables
IPTABLESSAVE=/sbin/iptables-save
IPTABLESRESTORE=/sbin/iptables-restore
EXTERNAL="eth0"
INTERNAL="eth1"
# Set IP for local host, iptalbes may need it
# Without configuring ips, use the setting of devices $EXTERNAL and $INTERNAL in system
LOCAL_EX_IP=('11.12.13.14' '11.12.13.15'); # Here list all your external ip candidates
#LOCAL_IN_IP=192.168.0.1 #
# Set your forward chain name, CFORWARD as default
# You may also define it as iptables' FORWARD, but it is dangers for unexpect change.
# CHAIN_NAME='CFORWARD'
# standard format of configuration
# MAPPING_TYPE LOCAL_PORT DEST_IP:DEST_PORT
# Be care of port conflict.
# the 4th domain of config is access limit rule
# only ips in '[]' are permited to use the port mapping
# use '#' to part each ips, DO NOT use any space in the ip limit part
# types like 12.34.56.78 and 12.34.56.78/16 are supported
# You may add your portmapping table beloww:
MAP_RULE=(
"tcp 21 192.168.0.2:21"
"tcp 22 192.168.0.3:22"
"tcp 80 192.168.0.13:8080"
"tcp 443 192.168.1.3:443 [12.34.56.0/24#58.156.232.144/28#192.168.0.0/24]"
"tcp 1001 192.168.1.2:3306 [12.34.56.78]"
);
# set ips if not configured before
if [[ $LOCAL_EX_IP = '' ]]
then
LOCAL_EX_IP=($(/sbin/ifconfig $EXTERNAL|grep inet\ addr:|cut -d':' -f2|cut -d' ' -f1))
fi
if [[ $LOCAL_IN_IP = '' ]]
then
LOCAL_IN_IP=$(/sbin/ifconfig $INTERNAL|grep inet\ addr:|cut -d':' -f2|cut -d' ' -f1)
fi
if [[ $CHAIN_NAME = '' ]]
then
CHAIN_NAME='CFORWARD'
fi
# check configuration
MAX_LINE=$(for((index=0; index<${#MAP_RULE[@]}; index++))
do
echo ${MAP_RULE[index]}|cut -d' ' -f2;
done | sort | uniq -c|sort|tail -1)
MAX_NUM=$(echo $MAX_LINE|awk '{print $1;}');
if [ $MAX_NUM -gt 1 ]
then
echo "[Error] Duplicat port found : $(echo $MAX_LINE|awk '{print $2;}')";
echo "Please check your configuration";
exit 1;
fi
# modprobe ftp modules
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
# flush existed nat rules
$IPTABLES -t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
$IPTABLES -t nat -F OUTPUT
$IPTABLES -t nat -F PREROUTING
#$IPTABLES -t nat -X
($IPTABLES -N $CHAIN_NAME && $IPTABLES -A FORWARD -j $CHAIN_NAME) 2>/dev/null
$IPTABLES -F $CHAIN_NAME
${IPTABLESSAVE}|grep -v SNAT|${IPTABLESRESTORE}
# Execute portmap rule
for((index=0; index<${#MAP_RULE[@]}; index++)){
rule=${MAP_RULE[index]};
protocol=$(echo $rule|cut -d' ' -f1);
out_port=$(echo $rule|cut -d' ' -f2);
map_address=$(echo $rule|cut -d' ' -f3);
map_server=$(echo $map_address|cut -d':' -f1);
map_port=$(echo $map_address|cut -d':' -f2);
allow_access=$(echo $rule|cut -d' ' -f4|cut -d'[' -f2|cut -d']' -f1);
if [[ $allow_access != '' ]]
then
allow_ip=(`echo $allow_access|tr '#' '\n'`);
else
allow_ip=();
fi
(for((ex_index=0; ex_index<${#LOCAL_EX_IP[@]}; ex_index++)){
$IPTABLES -t nat -A PREROUTING -d ${LOCAL_EX_IP[ex_index]} -p $protocol --dport $out_port -j DNAT --to $map_address
$IPTABLES -t nat -A OUTPUT -d ${LOCAL_EX_IP[ex_index]} -p $protocol --dport $out_port -j DNAT --to $map_address
# Add the upper command so that the firewall itself can also reach the port map server.
} && \
$IPTABLES -t nat -A POSTROUTING -d $map_server -p $protocol --dport $map_port -j SNAT --to $LOCAL_IN_IP && \
if [[ ${#allow_ip[@]} -gt 0 ]]
then
for((ip_index=0; ip_index<${#allow_ip[@]}; ip_index++)){
$IPTABLES -A $CHAIN_NAME -p $protocol -s ${allow_ip[ip_index]} -d $map_server --dport $map_port -j ACCEPT
}
$IPTABLES -A $CHAIN_NAME -p $protocol -d $map_server --dport $map_port -j DROP
else
$IPTABLES -A $CHAIN_NAME -p $protocol -d $map_server --dport $out_port -j ACCEPT
fi ) &> /dev/null
if [ "$?" -ne 0 ]
then
echo "Unknown mapping rule: \"$rule\"";
echo "Break down for pity!"
exit 1;
fi
}
echo Setting port map done!
exit 0;| I | Attachment | Action | Size | Date | Who | Comment |
|---|---|---|---|---|---|---|
| | nat-sample.jpg | manage | 87.1 K | 09 May 2008 - 02:41 | Main.yfang | NAT Sample |