前言
本文对重要的表和链进行了实验验证,包括filter表中的INPUT/OUTPUT/FORWARD链,NAT表中的POSTROUTING/PREROUTING链。
一、iptables简介
iptables原理
iptables是用户空间配置规则,控制内核netfilter对包进行过滤。
数据总共有三个流向:
本机接收数据:网卡接收数据----->PREROUTING链中规则过滤----->INPUT链中规则过滤
本机转发数据:网卡接收数据----->PREROUTING链中规则过滤----->路由判断是否转发---->FORWARD---->匹配路由---->POSTROUTING
本机发送数据:网卡接收数据---->OUTPUT---->匹配路由----->POSTROUTING
iptalbes 四表五链:
iptables的四个表iptable_filter,iptable_mangle,iptable_nat,iptable_raw,默认表是filter(没有指定表的时候就是filter表)。
iptables的五个链PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING。
每个表中都包括几种链,当匹配PREROUTING链时,需要先匹配raw表中的PREROUTING链,在匹配mangle表中的PREROUTING链,最后匹配nat表中的PREROUTING链。
表和链非常多,常用的如下:
filter表中的INPUT/OUTPUT/FORWARD
nat表中的PREROUTING/POSTROUTING
iptalbes常用方法
1.iptables 规则从一个链的自上而下匹配,需要优先匹配的规则放在最前面。
2.黑名单:前面的规则都是对流量的过滤,最后一条规则全部流量放行。
3.百名单:前面规则对特定流量放行,最后一条规则拒绝全部流量。
实验环境
虚拟机搭建如下实验环境,v2相当于是网关。
- 添加虚拟网卡vmnet1 vmnet3并设置网段。
- 将虚拟网卡设置到对应的虚拟机当中,v1设置vmnet1 v2设置vmnet1和vmnet3 v3设置vmnet3。
- 设置虚拟网卡的静态ip地址
以v1为例
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
#BOOTPROTO="dhcp" //动态ip,每次启动可能会变
BOOTPROTO="static" //设置成静态ip
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens33"
UUID="322cc9d8-1383-40d8-a115-c8b66474d500"
DEVICE="ens33"
ONBOOT="yes" //网卡开机自启动
IPADDR=192.168.4.3 //静态ip地址
NETMASK=255.255.255.0
GATEWAY=192.168.4.2 //默认网关,设置后会自动增加默认路由
PREFIX=24
DNS1=8.8.8.8
DNS2=114.114.114.114
service network restart //重启网卡
V2 需要设置ens33和ens37两张网卡,V3需要将ens33网卡设置成192.168.3.3
4. 打开V2的转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward ##打开临时转发功能
##设置永久转发功能
#Centos6 :
vi /etc/sysctl.conf
将net.ipv4.ip_forward = 0修改为net.ipv4.ip_forward= 1
#Centos7 :
vi /usr/lib/sysctl.d/00-system.conf
加入net.ipv4.ip_forward=1
到此V1能够Ping通v3
二、filter表
FORWARD
V2模拟一个防火墙
所有需要转发的流量都要匹配FORWARD链中的规则。
V2不转发任何数据包
iptables -A FORWARD -j DROP #直接将数据包丢弃,没有任何回应
iptables -A FORWARD -j REJECT #将数据包丢弃并且回应端口不可达icmp包
192.168.4.3 ping 192.168.3.3 依次增加一下两条规则
iptables -I FORWARD -p icmp -s 192.168.4.3 --icmp-type 8 -j ACCEPT
#允许原ip为192.168.4.3 type为8的数据包通过,icmp请求包能匹配到这条规则到达V3,但是V3的响应包只能匹配最后一条丢弃数据包的规则所以响应包不能到达V1。
iptables -I FORWARD -p icmp -d 192.168.4.3 --icmp-type 0 -j ACCEPT
#允许目的Ip 192.168.4.3 type为0的icmp 包通过,icmp响应包会匹配这条规则,所以这时192.168.4.3能ping通192.168.3.3。
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
30 2520 ACCEPT icmp -- * * 0.0.0.0/0 192.168.4.3 icmptype 0
81 6804 ACCEPT icmp -- * * 192.168.4.3 0.0.0.0/0 icmptype 8
904 75936 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
以上两条规则能够使192.168.4.128 ping通192.168.3.3但是3.3不能ping通4.3,要使3.3能Ping通4.3还需要增加以下规则
iptables -I FORWARD -p icmp -d 192.168.3.3 --icmp-type 0 -j ACCEPT
iptables -I FORWARD -p icmp -s 192.168.3.3 --icmp-type 8 -j ACCEPT
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
90 7560 ACCEPT icmp -- * * 0.0.0.0/0 192.168.3.3 icmptype 0
111 9324 ACCEPT icmp -- * * 192.168.3.3 0.0.0.0/0 icmptype 8
35 2940 ACCEPT icmp -- * * 0.0.0.0/0 192.168.4.3 icmptype 0
86 7224 ACCEPT icmp -- * * 192.168.4.3 0.0.0.0/0 icmptype 8
925 77700 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
下面这一条规则就相当于上面四条规则:
iptables -I FORWARD -p icmp -j ACCEPT
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
38 3192 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 # 只要是icmp包都能通过
1002 84168 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
INPUT/OUTPUT
INPUT:送达本机的包都要经过INPUT链进行过滤
V3上设置这条规则,v1就不能ping通v3,v3也不能ping通v1
iptables -I INPUT -p icmp -s 192.168.4.3 -j REJECT
##来自192.168.4.3的icmp都直接拒绝,v1 Ping v3,v1到v3的请求包被据,v3 ping v1 v1的响应包被拒
OUTOUT:本机发送出去的包都要通过OUTPUT链进行过滤
V3上设置这条规则
iptables -I OUTPUT -p icmp -j DROP
#本机发送出去的所有icmp包都会被丢弃,v1 ping v3时,请求包到达了v3,但是v3的响应包被OUTPUT链过滤掉了;v3 ping v1时,请求包就把过滤掉了。
三、NAT表
V2模拟一个NAT网关
POSTROUTING
iptables -t nat -A POSTROUTING -j SNAT --to 1.1.1.1
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
211 20006 SNAT all -- * * 0.0.0.0/0 0.0.0.0/0 to:1.1.1.1
任意原地址发往任意目的地址的任意协议的数据包,经过POSTROUTING都要将原地址改写成1.1.1.1
ping 192.168.3.3 对 V1 V2 V3进行抓包
V1
v1对v2进行的nat转换没有任何的感知
V2
conntrack -L
icmp 1 29 src=192.168.4.3 dst=192.168.3.3 type=8 code=0 id=14688 src=192.168.3.3 dst=1.1.1.1 type=0 code=0 id=14688 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1
conntrack v1.4.4 (conntrack-tools): 1 flow entries have been shown.
v2从ens33收到原始数据包,经过POSTROUTING将icmp包的原地址改写成1.1.1.1,发送到192.168.3.3,同时在conntract表中记录一条连接跟踪项。后续该链接通信直接匹配conntract来改写链接的状态。回包时直接匹配conntract映射表将目的地址由1.1.1.1改写成192.168.4.3。
V3
icmp 1 29 src=1.1.1.1 dst=192.168.3.3 type=8 code=0 id=17166 src=192.168.3.3 dst=1.1.1.1 type=0 code=0 id=17166 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1
V3上看到请求包的原地址为1.1.1.1,响应时将1.1.1.1作为目的地址发送给v2。
PREROUTING
iptables -t nat -A PREROUTING -j DNAT --to-destination 192.168.3.3
num pkts bytes target prot opt in out source destination
1 1 84 DNAT all -- * * 0.0.0.0/0 0.0.0.0/0 to:192.168.3.3
ping 1.1.1.1对 V1 V2 V3进行抓包
V1
V2
icmp 1 29 src=192.168.4.3 dst=1.1.1.1 type=8 code=0 id=17798 src=192.168.3.3 dst=192.168.4.3 type=0 code=0 id=17798 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1
V2 ens33收到目的地址为1.1.1.1的包,匹配PREROUTING的规则,将目的地址改成192.168.3.3,后经过路由从ens37网卡发出,同时在conntract表中记录一条连接跟踪项。回包时先匹配conntract链,将原地址由192.168.3.3改成1.1.1.1。
V3
icmp 1 29 src=192.168.4.3 dst=192.168.3.3 type=8 code=0 id=17798 src=192.168.3.3 dst=192.168.4.3 type=0 code=0 id=17798 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1
v1ping任意地址,最后数据包都会到达v3。
参考
iptables的四表五链与NAT工作原理
Iptables教程
iptables之forward转发
linux 中增加路由(route)命令详解
使用IPtables配置虚拟路由器
linux conntrack