在Linux系统使用iptables实现外网访问内网

转自:zong_xp
0 背景
考虑一种网络拓扑应用情景,一个内部局域网中有多台服务器提供不同的服务,如web服务、ftp服务、ssh、telnet等,通过服务器(或网关、防火墙)连接外部网络,如果外部网络上的主机需要访问这些服务器,则需要在网关上实现转发。
再转述成另一种应用场合,多台设备连接到一台服务器,服务器有2个网卡,分别连接内外网。外网无法直接访问设备上的数据、服务。在服务器上实现转发后,则可达到目的。
网络拓扑如下:
比如,可以通过服务器的8081端口访问1号设备的web服务,8082端口访问2号设备web,这样可以在外部网络对内网设备进行参数配置、调整。类似地,通过2321访问1号设备的telnet服务,2322访问2号设备telnet,以方便登陆设备系统,进行设备状态监控,日志处理,等等。
本文将直接引用此网络拓扑图中的名称及ip地址。实际使用配置根据实际情况修改。另外说明一下,不必拘泥于本文给出的名称。像拓扑图中的“设备”,可以使用一台安装linux的服务器替换。其它的类似。
一、原理
在linux系统使用iptables实现防火墙、数据转发等功能。iptables有不同的表(tables),每个tables有不同的链(chain),每条chain有一个或多个规则(rule)。本文利用nat(network address translation,网络地址转换)表来实现数据包的转发。iptables命令要用-t来指定表,如果没有指明,则使用系统缺省的表“filter”。所以使用nat的时候,就要用“-t nat”选项了。
nat表有三条缺省的链,它们分别是prerouting、postrouting和output。
先给出nat结构,如下图:
prerouting:在数据包传入时,就进到preroutiing链。该链执行的是修改数据包内的目的ip地址,即dnat(变更目的ip地址)。prerouting只能进行dnat。因为进行了dnat,才能在路由表中做判断,决定送到本地或其它网口。
postrouting:相对的,在postrouting链后,就传出数据包,该链是整个nat结构的最末端。执行的是修改数据包的源ip地址,即snat。postrouting只能进行snat。
output:定义对本地产生的数据包的目的nat规则。
每个数据包都会依次经过三个不同的机制,首先是prerouting(dnat),再到路由表,最后到postrouting(snat)。下面给出数据包流方向:
文中的网络拓扑图所示的数据包,是从eth0入,eth1出。但是,无论从eth0到eth1,还是从eth1到eth0,均遵守上述的原理。就是说,snat和dnat并没有规定只能在某一个网口(某一侧)。
顺便给出netfilter的完整结构图:
二、实现
出于安全考虑,linux系统默认是禁止数据包转发的。所谓转发即当主机拥有多于一块的网卡时,其中一块收到数据包,根据数据包的目的ip地址将包发往本机另一网卡,该网卡根据路由表继续发送数据包。这通常就是路由器所要实现的功能。
配置linux系统的ip转发功能,首先保证硬件连通,然后打开系统的转发功能
cat /proc/sys/net/ipv4/ip_forward,该文件内容为0,表示禁止数据包转发,1表示允许,将其修改为1。可使用命令echo 1 > /proc/sys/net/ipv4/ip_forward修改文件内容,重启网络服务或主机后效果不再。若要其自动执行,可将命令echo 1 > /proc/sys/net/ipv4/ip_forward 写入脚本/etc/rc.d/rc.local 或者在/etc/sysconfig/network脚本中添加 forward_ipv4=yes
但在我的系统中没有这两个文件,因此可以修改/etc/sysctl.conf文件,将net.ipv4.ip_forward=1的注释取消即可
根据拓扑图,一一实现不同ip、不同端口的映射,如下命令为一种示例形式:
# 第一台设备的telnet服务iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 2321 -j dnat --to 100.100.100.101:23iptables -t nat -a postrouting -o eth1 -d 100.100.100.101 -p tcp --dport 23 -j snat --to 100.100.100.44# 第二台设备的telnet服务iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 2322 -j dnat --to 100.100.100.102:23iptables -t nat -a postrouting -o eth1 -d 100.100.100.102 -p tcp --dport 23 -j snat --to 100.100.100.44 # 第一台设备的web服务iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 8081 -j dnat --to 100.100.100.101:80iptables -t nat -a postrouting -o eth1 -d 100.100.100.101 -p tcp --dport 80 -j snat --to 100.100.100.44# 第二台设备的web服务iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 8082 -j dnat --to 100.100.100.102:80iptables -t nat -a postrouting -o eth1 -d 100.100.100.102 -p tcp --dport 80 -j snat --to 100.100.100.44
以第一台设备转发命令为例,用白话解释一下。
第一条是prerouting链,只能进行dnat,该命令对从eth0进入且目的ip为172.18.44.44(注:可以用-s指明数据包来源地址,但这时无法知道来源ip是多少,虽然可以用网段的做法,但用-d则指定必须一定唯一的是本机的eth0地址,相对好一点),端口号为2321的数据包进行目的地址更改,更改为100.100.100.101,端口为23,亦即此包的目的地为第一台设备的telnet服务。
第二条是postrouting链,只能进行snat,即对先前已经dnat过的数据包修改源ip地址。这样,这个数据包达到第一台设备时,源ip地址、目的ip地址,均为100.100.100.0/24网段了。
上述命令的snat有些冗余,可以做简化,命令如下:
# 第一台设备的telnet、web服务iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 2321 -j dnat --to 100.100.100.101:23iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 8081 -j dnat --to 100.100.100.101:80# 第二台设备的telnet、web服务iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 2322 -j dnat --to 100.100.100.102:23iptables -t nat -a prerouting -i eth0 -d 172.18.44.44 -p tcp --dport 8082 -j dnat --to 100.100.100.102:80# 源ip地址snatiptables -t nat -a postrouting -o eth1 -d 100.100.100.0/24 -j snat --to 100.100.100.44
实际中使用的命令可能还有变化(简化),本文不再展示。
三、测试
为了保证文中所述的正确性,本节列出操作结果,以及实验过程的信息。服务器(网关)上的路由表如下:
root@latelee:test# routekernel ip routing tabledestination gateway genmask flags metric ref use iface100.100.100.0 * 255.255.255.0 u 0 0 0 eth1172.18.0.0*255.255.0.0u000eth0
可以看到服务器上有2个网卡,网段都不相同。iptables的nat表如下:
root@latelee:~# iptables -l -t natchain prerouting (policy accept)target prot opt source destination dnat tcp -- anywhere 172.18.44.44 tcp dpt:2324 to23chain input (policy accept)target prot opt source destination chain output (policy accept)target prot opt source destination chain postrouting (policy accept)target prot opt source destination snat all -- anywhere 100.100.100.0/24 to:100.100.100.44
可以看到,prerouting和postrouting各有一条规则,这些规则由上文命令所产生。对应的,在第一号设备上查看路由信息,如下:
root@latelee:~# routekernel ip routing tabledestination gateway genmask flags metric ref use iface100.100.100.0 * 255.255.255.0 u 0 0 0 eth0172.18.0.0 * 255.255.0.0 u 0 0 0 eth1default 100.100.100.44 0.0.0.0 ug 0 0 0 eth0
可以看到这台设备有2个网卡,默认网关为服务器的ip地址。但是,其中一个网卡eth1竟然和pc所在网段相同!如果没有进行源ip地址修改(伪装),会匹配到eth1这个网口,无法匹配eth0。
在外网的pc上对设备进行telnet,设备抓包信息如下:
ip 100.100.100.44.32253 > 100.100.100.101.2323: flags [p.], seq 1:4, ack 16, win 256, length 3ip 100.100.100.101.2323 > 100.100.100.44.32253: flags [p.], seq 16:19, ack 4, win 2190, length 3ip 100.100.100.44.32253 > 100.100.100.101.2323: flags [p.], seq 4:25, ack 19, win 256, length 21ip 100.100.100.101.2323 > 100.100.100.44.32253: flags [p.], seq 19:34, ack 25, win 2190, length 15
可见,所有包的ip段都相同。在服务器上对内网eth1进行抓包,由于进行了dnat和snat,此网卡数据包ip地址还是100.100.100.0/24网段,如下:
ip 100.100.100.44.32253 > 100.100.100.101.telnet: flags [.], ack 1, win 256, length 0ip 100.100.100.101.telnet > 100.100.100.44.32253: flags [p.], seq 1:16, ack 1, win 2190, length 15ip 100.100.100.44.32253 > 100.100.100.101.telnet: flags [p.], seq 1:4, ack 16, win 256, length 3ip 100.100.100.101.telnet > 100.100.100.44.32253: flags [p.], seq 16:19, ack 4, win 2190, length 3
但是,在服务器eth0抓包,将会是172.18.0.0/16的网段数据包:
ip 172.18.44.142.32253 > 172.18.44.44.2324: flags [p.], seq 18:20, ack 154, win 255, length 2ip 172.18.44.44.2324 > 172.18.44.142.32253: flags [p.], seq 154:156, ack 20, win 2190, length 2ip 172.18.44.44.2324 > 172.18.44.142.32253: flags [f.], seq 156, ack 20, win 2190, length 0ip 172.18.44.142.32253 > 172.18.44.44.2324: flags [.], ack 157, win 255, length 0ip 172.18.44.142.32253 > 172.18.44.44.2324: flags [f.], seq 20, ack 157, win 255, length 0ip 172.18.44.44.2324 > 172.18.44.142.32253: flags [.], ack 21, win 2190, length 0
从抓包分析,本文所用命令已经能正确进行dnat和snat了。
四、其它
建议在使用iptabls指令时,使用root用户进行操作,否则容易失败
保存iptables配置方法:
iptables-save > /etc/iptables.up.rules
配置iptables开机加载
iptables-save>/etc/iptables.up.rulesecho -e '#!/bin/bash /sbin/iptables-restore /etc/network/if-pre-up.d/iptableschmod +x /etc/network/if-pre-up.d/iptables
本地测试指令
iptables -t nat -a prerouting -i wlan0 -d 192.168.11.100 -p tcp --dport 8081 -j dnat --to 192.168.10.101:80iptables -t nat -a postrouting -o eth0 -d 192.168.10.101 -p tcp --dport 80 -j snat --to 192.168.10.52
原文标题:linux之iptables端口转发:外网访问内网
文章出处:【微信公众号:linux爱好者】欢迎添加关注!文章转载请注明出处。


工业物联网时代,CC-LinkIETSN网络解决方案在制造业大放光彩
realme X2不失所望,6400万四摄+骁龙730G+30W VOOC闪充
滤波电容容值与所滤噪声频率的关系
Fitbit为何打赢AppleWatch? 功能合理 性价比高
场效应管厂商:山东科达半导体有限公司简介
在Linux系统使用iptables实现外网访问内网
瞬态抑制二极管TVS的选择
华为P10最新消息:华为P10闪存门风波未平,华为P10“wifi硬件门”风波又起,网友还会买账吗?
SIM卡座的基本知识你了解多少
STC15系列单片机与迪文DGUS屏应用(五):模拟调试
一文详解阻抗变换器
一款安全实用的智能门锁——TCL物联网智能锁K2
全球晶圆代工市场创下十年最高历史水平
简易压力测量设备的制作
vivo执行副总裁胡柏山:V1是自研影像芯片,将由X70系列首发
PCB仿真软件的电磁场求解器分类
电子管组成的无线对讲机的制作与设计
友谊的小船说翻就翻:东芝起诉西部数据 索赔10.7亿美元
LT6703具有2V迟滞的微电源电压监视器
将多个分立电容集成到固态器件中