iptables 使用详解

iptables五表五链

五表table

  • filter 过滤数据包 (default table)常用

  • nat 网络地址转换 (端口映射,地址映射等)常用

  • mangle 对特定的数据报文进行修改

  • raw 设置raw时一般是为了不再让iptables做数据包的链接跟踪处理,加快封包穿越防火墙的速度,提高性能

  • security 优先级最高,用于强制访问控制(MAC)网络规则,由Linux安全模块实现如SElinux

    优先级从高到低顺序为:

    security→raw→mangle→nat→filter

五链CHAIN(内置链)

  • PRE_ROUTING 所有进入数据包都要经由此策略(数据包进入路由表之前)

  • INPUT 进来的数据包应用此策略(数据包通过路由表后目的为本机)

  • OUTPUT 流出的数据包应用此策略(数据包由本机产生,向外流出)

  • FORWARD 数据包流经本机进行转发(数据包流过路由表后,目的地不为本机)

  • POST_ROUTING 所有流出数据包都要经由此策略(数据包发送到网卡接口前)

从表到链的对应关系 2022-10-31-21-02-34-image.png

可以使用iptables -t tables -nvL 查看

raw 表中的规则可以被哪些链使用:PREROUTING,OUTPUT

mangle 表中的规则可以被哪些链使用:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING

nat 表中的规则可以被哪些链使用:PREROUTING,OUTPUT,POSTROUTING(centos7中有INPUT,centos6中没有)

filter 表中的规则可以被哪些链使用:INPUT,FORWARD,OUTPUT

2022-10-31-20-26-10-image

数据报文流向

  • 流入本机: 数据包→PRE_ROUTING→INPUT→用户空间进程

  • 流出本机: 用户空间进程→OUTPUT→POST_ROUTING

  • 转发: 数据包→PRE_ROUTING→FORWARD→POST_ROUTING

iptables 命令使用

iptables基本语法命令格式

iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作

iptables [-t 表名] 管理选项 [链名] [匹配条件] [-j 动作处理]
例如:
iptables -t filter -A INPUT -s 10.11.12.12 -j DROP

表名、链名:指定iptables命令所操作的表和链,未指定表名时将默认使用filter表; 管理选项:表示iptables规则的操作方式,比如:插入、增加、删除、查看等; 匹配条件:指定要处理的数据包的特征,不符合指定条件的数据包不处理; 动作处理:指数据包的处理方式,比如:允许ACCEPT、拒绝REJECT、丢弃DROP、日志LOG等;

管理选项

iptables 命令的常用管理选项
# 规则管理命令
-A, --append chain rule-specification 在指定链 chain 的末尾插入指定的规则,也就是说,这条规则会被放到最后,最后才会被执行。规则是由后面的匹配来指定。
-I, --insert chain [rulenum] rule-specification 在链 chain 中的指定位置插入一条或多条规则。如果指定的规则号是1,则在链的头部插入。这也是默认的情况,如果没有指定规则号。
-D, --delete chain rule-specification -D, --delete chain rulenum 在指定的链 chain 中删除一个或多个指定规则。
-R num:Replays替换/修改第几条规则

# 查看管理命令
-n:使用数字形式显示输出结果
-v:查看规则列表时显示详细的信息
--line-numbers:查看规则列表时,同时显示规则在链中的顺序号
-L:列出指定链中所有的规则,未指定链名,则列出表中的所有链

# 链管理命令(这都是立即生效的)
-P, --policy chain target :为指定的链 chain 设置策略 target。注意,只有内置的链才允许有策略,用户自定义的是不允许的。
-F, --flush [chain] 清空指定链 chain 上面的所有规则。如果没有指定链,清空该表上所有链的所有规则。
-N, --new-chain chain 用指定的名字创建一个新的链。
-X, --delete-chain [chain] :删除指定的链,这个链必须没有被其它任何规则引用,而且这条上必须没有任何规则。如果没有指定链名,则会删除该表中所有非内置的链。
-E, --rename-chain old-chain new-chain :用指定的新名字去重命名指定的链。这并不会对链内部造成任何影响。
-Z, --zero [chain] :把指定链,或者表中的所有链上的所有计数器清零。

#帮助
-h:查看命令帮助信息

匹配条件

基本匹配条件

基本匹配条件: 无需加载模块有iptables/netfilter自行提供

[!] -s --sources  匹配来源地址IP-ADDR[/mask],可以写多个,逗号隔开.加叹号"!"表示除这个IP外。
[!] -d --destination 匹配目标地址
[!] -i --in-interface 网卡名称 匹配从这块网卡流入的数据
[!] -o --out-interface 网卡名称 匹配从这块网卡流出的数据
[!] -p --protocol 匹配协议,如tcp,udp,icmp等 参考:/etc/protocols

扩展条件模块

扩展匹配条件需要加载(/usr/ilb64/xtables/*.so),可使用man iptables-extensions 查看帮助

隐式扩展 : -p指明了特定协议后,无需在使用-m 选项指定模块,不需要手动加载模块(例如tcp)
隐式扩展
TCP协议扩展
[!] --source-port , --sport port[:port] #匹配报文源端口或者范围
[!] --destination-port , --dport port[:port] #匹配报文目标端口或者范围
[!] --tcp-flags mask comp
     mask 需检测的标记位列表 用,隔开 例:SYN,ACK,FIN等
     comp 在mask列表中必须为1的标记位列表,无指定则为0 用,分隔tcp协议的扩展项
--tcp-flags SYN,ACK,FI  SYN  #表示要检查标志位为SYN,ACK,FIN 三个,其中SYN必须为1 其余必须为0 (第一次握手)
--syn  #用于匹配第一次握手等价于 --tcp-flags SYN,ACK,FIN  SYN
--tcp-flags SYN,ACK,FIN  SYN,ACK #表示要检查标志位为SYN,ACK,FIN 三个,其中SYN和ACK必须为1 其余必须为0 (第二次握手)


#示例1: 禁止第一次握手
iptables -t filter -A INPUT -s 10.0.0.201 -p tcp --syn -j REJECT

#此时新建链接无法连入,已建立连接的主机不受影响.
ssh 10.0.0.41
ssh: connect to host 10.0.0.41 port 22: Connection refused



#示例2: 禁止指定地址访问web服务

# 未加规则前
curl 10.0.0.41
<html>
<head><title>Index of /</title></head>
<body>
<h1>Index of /</h1><hr><pre><a href="../">../</a>
<a href="centos7/">centos7/</a>                                           03-Nov-2022 07:32                   -
</pre><hr></body>
</html>


#添加规则禁止10.0.0.201 访问10.0.0.41的80端口
iptables -t filter -A INPUT -s 10.0.0.201 -p tcp --dport 80 -j REJECT

# 添加策略后
curl 10.0.0.41
curl: (7) Failed connect to 10.0.0.41:80; Connection refused
UDP协议扩展
[!] --source-port , --sport port[:port] #匹配报文源端口或者范围
[!] --destination-port , --dport port[:port] #匹配报文目标端口或者范围
ICMP协议扩展
[!]--icmp-type {type[/code]|typename}
     type/code
       0/0 echo-reply     #icmp应答
       8/0 echo-request   #icmp请求
#例如: --icmp-type 8 | --icmp-type echo-request
iptables -t filter -A INPUT -s 10.0.0.201 -p icmp --icmp-type echo-request -j REJECT
#例如:拒绝指定地址的icmp包

#添加策略前
ping 10.0.0.41
PING 10.0.0.41 (10.0.0.41) 56(84) bytes of data.
64 bytes from 10.0.0.41: icmp_seq=1 ttl=64 time=0.805 ms
64 bytes from 10.0.0.41: icmp_seq=2 ttl=64 time=0.351 ms


iptables -t filter -A INPUT -s 10.0.0.201 -p icmp -j DROP
#命令拆解:
#  -t: 指定表(默认为filter表),指定filter表时可以不写
#  -A: 在指定链的末尾添加一条新的规则
#  -s: 指定来源地址
#  -p: 指定协议,此处为禁ping
#  -j: 指定动作


iptables -nL #查看是否生效 查看详细资料可加-v 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  10.0.0.201           0.0.0.0/0           

#添加策略后
ping 10.0.0.41
PING 10.0.0.41 (10.0.0.41) 56(84) bytes of data.
--- 10.0.0.41 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3019ms
#此时双向都无法ping通




#禁止10.0.0.201 ping通10.0.0.41,但10.0.0.41 可以ping通 10.0.0.201
 iptables -t filter -A INPUT  -s 10.0.0.201 -p icmp --icmp-type echo-request -j REJECT
显式扩展

显式扩展: 手动加载扩展模块,必须使用--m 指定要加载的模块名称

-m --match matchname [per-match-options]

扩展模块使用帮助

  • centos7,8: man iptables-extensions

  • centos6: man iptables

1. multiport 扩展模块

以离散方式定义多个端口匹配,最多指定15个

#指定多个源端口
[!] --source-ports, --sports port_num[port_num1|,port_num:port_num]

#指定多个目标端口
[!] --destination-ports, --dports port_num[port_num1|,port_num:port_num]

#指定多个源或者目标端口
[!] --ports,  port_num[port_num1|,port_num:port_num]
#示例1:禁止指定地址访问22,80-88,443端口

#指定策略前

curl 10.0.0.41
<html>
<head><title>Index of /</title></head>
<body>
<h1>Index of /</h1><hr><pre><a href="../">../</a>
<a href="centos7/">centos7/</a>                                           03-Nov-2022 07:32                   -
</pre><hr></body>
</html>
[root@vm-centos7 ~]# ssh 10.0.0.41
root@10.0.0.41's password: 

#指定策略
iptables -t filter -A INPUT -s 10.0.0.201 -p tcp -m multiport --dports 22,80:88,443 -j REJECT


#指定策略后


ssh 10.0.0.41
ssh: connect to host 10.0.0.41 port 22: Connection refused

curl 10.0.0.41                                                                                 
curl: (7) Failed connect to 10.0.0.41:80; Connection refused
2. string 扩展模块

对报文中的应用层数据做字符串模式匹配

--algo {bm|kmp} #字符串的匹配方式
    bm: Boyer-moore
    kmp: Knuth-pratt-morris 
--icase  #忽略大小写
--from offset  #开始偏移量
--to offset  #结束偏移量
[!] --string #要检测的字符串模式
[!] --hex-string #要检测的字符串模式,16进制




#例如:禁止访问包含baidu字符串的网址
iptables -t filter -A OUTPUT -p tcp --dport 80 -m string --algo bm  --string "baidu" -j REJECT
3. iprange 扩展模块

指定连续的IP地址范围

[!] --src-range from[-to]  # 源IP地址范围
[!] --dst-range from[-to] # 目标IP地址范围


#例如: 禁止200-250机器访问远程主机10.0.0.41的80端口
iptables -t filter -A INPUT -d 10.0.0.41 -p tcp  --dport 80 -m iprange --src-range 10.0.0.200-10.0.0.250 -j REJECT 
4. mac 扩展模块

mac模块指定源mac地址

[!] --mac-source XX:XX:XX:XX:XX:XX


#例如:禁止指定mac地址访问本机80和443端口
iptables -t filter -A INPUT -p tcp -m multiport --dports 80,443 -m mac --mac-source 00:0c:29:b5:d2:43 -j REJECT


iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 80,443 MAC 00:0C:29:B5:D2:43 reject-with icmp-port-unreachable
5. time 扩展模块

根据报文到达的时间与指定的时间范围进行匹配(centos8 和rocky有问题)

--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]] #起始日期
--datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]] #结束日期
--timestart hh:mm[:ss] #起始时间  
--timestop hh:mm[:ss] #结束时间  
[!] --monthdays day[,day...] # 每个月的几号
[!] --weekdays  day[,day...]  # 星期几
--kerneltz #内核时间(UTC时区) 不建议使用,centos7默认为UTC
#注意 time模块的时间为UTC时区 如需换算需要-8 (UTC+8)中国时间


#例如: 15:00-16:45分禁止访问淘宝网站(注意时间要使用UTC时间进行转换)
iptables -A OUTPUT -p tcp -m multiport --dports 80:443 -m string --algo bm --string "taobao.com" -m time --timestart 7:00 --timestop 8:53 -j REJECT
6. connlimit 扩展模块

根据客户端ip做并发连接数数量匹配,可以防止ddos拒绝服务攻击

--connlimit-upto   #连接数量小于等于时匹配
--connlimit-above  #连接数量大于时匹配




#例如: 禁止指定地址的http并发连接数超过10次

#未指定策略前使用ab 并发100个连接,可以正常访问
ab  -c 100 -n 100 10.0.0.41/ 

Benchmarking 10.0.0.41 (be patient).....done

Server Software:        nginx/1.22.0
Server Hostname:        10.0.0.41
Server Port:            80

Document Path:          /
Document Length:        248 bytes

Concurrency Level:      100
Time taken for tests:   0.023 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      37000 bytes
HTML transferred:       24800 bytes
Requests per second:    4426.93 [#/sec] (mean)
Time per request:       22.589 [ms] (mean)
Time per request:       0.226 [ms] (mean, across all concurrent requests)
Transfer rate:          1599.58 [Kbytes/sec] received
......

#指定策略
iptables -t filter -A INPUT -s 10.0.0.201 -p tcp -m multiport --dports 80,443  -m connlimit --connlimit-above 10 -j REJECT



#指定策略后 超过10个连接数后无法访问
 ab -n 100 -c 11  10.0.0.41/

Benchmarking 10.0.0.41 (be patient)...apr_socket_recv: Connection refused (111)
Total of 1 requests completed
7. limit扩展模块

基于收发报文进行速率匹配控制,限流

--limit number[/second|/minute|/hour|/day]  # --limit 30/minute (每分钟通过30个包)
--limit-burst number   #前number个包不限制



例如: 只允许icmp 每分钟通过30个包(两秒一个),前5个包不限制
iptables -t filter -A INPUT -p icmp -m limit --limit 30/minute --limit-burst 5 -j ACCEPT

iptables -t filter -A INPUT -p icmp -j REJECT 

ping 10.0.0.41
PING 10.0.0.41 (10.0.0.41) 56(84) bytes of data.
64 bytes from 10.0.0.41: icmp_seq=1 ttl=64 time=0.236 ms
64 bytes from 10.0.0.41: icmp_seq=2 ttl=64 time=0.503 ms
64 bytes from 10.0.0.41: icmp_seq=3 ttl=64 time=0.328 ms
64 bytes from 10.0.0.41: icmp_seq=4 ttl=64 time=0.432 ms
64 bytes from 10.0.0.41: icmp_seq=5 ttl=64 time=0.577 ms
64 bytes from 10.0.0.41: icmp_seq=6 ttl=64 time=0.309 ms
64 bytes from 10.0.0.41: icmp_seq=7 ttl=64 time=0.427 ms
64 bytes from 10.0.0.41: icmp_seq=8 ttl=64 time=0.676 ms
64 bytes from 10.0.0.41: icmp_seq=9 ttl=64 time=0.411 ms
From 10.0.0.41 icmp_seq=10 Destination Port Unreachable
64 bytes from 10.0.0.41: icmp_seq=11 ttl=64 time=0.518 ms
From 10.0.0.41 icmp_seq=12 Destination Port Unreachable
64 bytes from 10.0.0.41: icmp_seq=13 ttl=64 time=0.578 ms
From 10.0.0.41 icmp_seq=14 Destination Port Unreachable
64 bytes from 10.0.0.41: icmp_seq=15 ttl=64 time=0.515 ms
From 10.0.0.41 icmp_seq=16 Destination Port Unreachable
64 bytes from 10.0.0.41: icmp_seq=17 ttl=64 time=0.662 ms
From 10.0.0.41 icmp_seq=18 Destination Port Unreachable
64 bytes from 10.0.0.41: icmp_seq=19 ttl=64 time=0.335 ms
From 10.0.0.41 icmp_seq=20 Destination Port Unreachable
8. state扩展模块

state扩展模块,可以根据"连接追踪机制"去检查联动的状态

需要依赖连接追踪库 /porc/net/nf_conntrack ,可使用lsmod |grep conntrack 查看是否开启 默认关闭状态,添加策略后可自动开启

conntrack机制: 追踪本机请求和响应之前的关系

# 连接追踪功能所容纳的最大连接数
cat /proc/sys/net/netfilter/nf_conntrack_max
31112
cat /proc/sys/net/nf_conntrack_max
31112
#查看已经了多少条

#临时修改
echo '100000' > /proc/sys/net/netfilter/nf_conntrack_max
或者 sysctl -w net.netfilter.nf_conntrack_max = 100000
#永久修改
vim /etc/sysctl.conf
net.netfilter.nf_conntrack_max = 100000
sysctl -p                         #读取修改后的配置


#查看ESTABLISHED超时时间(连接在conntrack表中保留的时间)
#/proc/sys/net/netfilter/这个目录下的文件都记录了对应协议的超时时间
cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established 
432000

对于state模块的连接而言,”连接”其中的报文可以分为5种状态(与TCP协议中的状态无任何关系),报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED

  • NEW: 新发起的请求,连接追踪信息库中不存在此链接的相关条目 (第一次发出请求)

  • ESTABLISHED: NEW状态之后,连接追踪库中为其建立的条目失效前期间内的所有通信状态(只要不是第一次后续的连接都视为ESTABLISHED)

  • RELATED: 新发起的但是与已有的连接相关联(相关的包)

    举个例子说明:

    FTP有两个链接:一个是传输控制命令的链接,一个是传输数据的链接。

    先建立起的链接是传输控制命令的链接,

    然后,由于链接里的某个命令,需要创建一个新的链接, 那么这个新的链接里的第1个数据包的状态就是RELATED状态 新连接后续的数据包的状态也是 ESTABLISHED 状态

  • INVALID: 无效的连接(一个包没有办法被识别,或者这个包没有任何状态,如:flag标记位不正确)

  • UNTRACKED: 未进行追踪的连接(报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接)

# 例如: 已建立连接的用户正常连接,新用户不可连接
iptables -t filter -A INPUT -m state ESTABLISHED -j ACCEPT #建立连接的用户正常连接
iptables -t filter -A INPUT -m state NEW -j REJECT #新用户不可连接

动作处理

处理动作(target) 也分为基本动作和扩展动作。以下列举一些常用的动作:

ACCEPT: 允许数据包通过
DROP: 直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应
QUEUE: 将数据包移交到用户空间
RETURN: 停止执行当前链中的后续规则,并返回到调用链(The Calling Chain)中
REJECT: 拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息
DNAT: 目标地址转换
SNAT: 源地址转换,解决内网用户用同一个公网地址上网的问题
MASQUERADE: IP伪装(NAT) 是 SNAT 的一种特殊形式,适用于动态ip
REDIRECT: 重定向,在本机做端口映射
LOG: 记录日志信息,除记录外不对数据包做任何其他操作,仍然匹配下一条规则 日志保存在/var/log/messages中
--log-level level #级别: debug,info,notice,warning,error,crit,emerg
--log-prefix prefix #日志前缀,用于区别不同的日志,最多29字符
iptables -t filter -A INPUT -s 10.0.0.201 -j DROP # 拒绝所有来自10.0.0.201的包
iptables -D INPUT 2 # 删除filter表中INPUT链的第二条规则
iptables -I INPUT 2 -s 10.0.0.42 -j ACCEPT # 将规则插入到filter表中的INPUT链的第二条
iptables -R INPUT 1 -s 10.0.0.41 -j REJECT # 将filter表中INPUT链中的第一条进行修改 

自定义链

使用自定义链可以更为高效,灵活的管理各个规则

-N:自定义一条新的规则链
-E:重命名自定义链  # oldchain  newchain
-X:删除自定义的空规则链


#例如:在filter表中新增一个自定义链
iptables -N WEB_TEST

iptables -vnL #查看是否生成自定义链
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain WEB_TEST (0 references)
 pkts bytes target     prot opt in     out     source               destination         

# 将规则添加到自定义链中
iptables -A WEB_TEST -s 10.0.0.201 -p tcp -m multiport --dport 80,443 -j REJECT


#将自定义链关联到内置链
iptables -A INPUT -j WEB_TEST


#查看定义链
 iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   76  4512 WEB_TEST   all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain WEB_TEST (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       10.0.0.201           0.0.0.0/0            multiport dports 80,443 reject-with icmp-port-unreachable

iptables保存与加载

使用iptables-save 输出重定向到文件可以持久保存

使用iptables-restore 输入重定向可加载配置

#例如:保存到文件
iptables-save > /root/iptables.rules

cat /root/iptables.rules

#Generated by iptables-save v1.8.4 on Wed Nov  9 15:21:18 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:WEB_TEST - [0:0]
-A INPUT -s 10.0.0.0/24 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j REJECT --reject-with icmp-port-unreachable
COMMIT
# Completed on Wed Nov  9 15:21:18 2022


# 加载配置
iptables-restore < /Rroot/iptables.rules 

iptables -vnL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   28  1624 ACCEPT     tcp  --  *      *       10.0.0.0/24          0.0.0.0/0            tcp dpt:22
    1    41 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
    0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 reject-with icmp-port-unreachable

#以上方式为手动加载,每次开关机后需要手动执行加载命令



#开机自动加载iptables规则
#方式一:
使用/etc/rc.d/rc.local 文件 在里面加入 iptables-restore < /PATH/iptable_file
(rc.local需要执行权限)
#方式二: 
安装iptables-services
通过查看services启动脚本找寻配置文件所在位置,一般存在于/etc/sysconfig/iptables下
使用iptables-save 重定向保存到脚本指定位置后(/etc/sysconfig/iptables) ,将iptables-server设置为开机自启,可以实现开机自动加载

cat /usr/lib/systemd/system/iptables.service
[Unit]
Description=IPv4 firewall with iptables
AssertPathExists=/etc/sysconfig/iptables
Before=network-pre.target
Wants=network-pre.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/iptables/iptables.init start
ExecReload=/usr/libexec/iptables/iptables.init reload
ExecStop=/usr/libexec/iptables/iptables.init stop
Environment=BOOTUP=serial
Environment=CONSOLETYPE=serial
StandardOutput=syslog
StandardError=syslog

 cat -n /usr/libexec/iptables/iptables.init |less 
    24  IPTABLES=iptables
    25  IPTABLES_DATA=/etc/sysconfig/$IPTABLES

FORWARD链

FORWARD链实现内外网流量控制

环境 web1 主机 172.16.1.2 网关指向forward 172.16.1.3 forward 防火墙主机 10.0.0.3 172.16.1.3 web2 主机 10.0.0.4 网关指向forward 10.0.0.3

开启linux转发方式

临时打开:
echo 1 > /proc/sys/net/ipv4/ip_forward
或
sysctl -w net.ipv4.ip_forward=1

永久打开:
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1         #将此行写入配置文件

sysctl -p                         #读取修改后的配置
 # web1和web2可以正常通讯
ping 172.16.1.2 -c 3
PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
64 bytes from 172.16.1.2: icmp_seq=1 ttl=63 time=0.444 ms
64 bytes from 172.16.1.2: icmp_seq=2 ttl=63 time=0.785 ms
64 bytes from 172.16.1.2: icmp_seq=3 ttl=63 time=1.04 ms

curl 172.16.1.2
web1 website



ping 10.0.0.4 -c 3
PING 10.0.0.4 (10.0.0.4) 56(84) bytes of data.
64 bytes from 10.0.0.4: icmp_seq=1 ttl=63 time=0.606 ms
64 bytes from 10.0.0.4: icmp_seq=2 ttl=63 time=0.645 ms
64 bytes from 10.0.0.4: icmp_seq=3 ttl=63 time=0.551 ms

curl 10.0.0.4
web2 website

至此准备环境已经完成

#控制转发,不允许web1访问web2,但是web2 可以访问web1

iptables -t filter -A FORWARD -m state --state ESTABLISHED -j ACCEPT 
#允许与已建立连接的主机通讯

iptables -t filter -A FORWARD   -s 10.0.0.4 -m state --state NEW -j ACCEPT
#允许源地址为10.0.0.4的机器进行转发(web2向外访问允许)

iptables -t filter -A FORWARD  -j REJECT
#最后拒绝所有

#或者

iptables -A FORWARD -s 10.0.0.4  -j ACCEPT 
#允许源地址为10.0.0.4的主机进行通讯

iptables -t filter -A FORWARD -d 10.0.0.4 -m state --state ESTABLISHED -j ACCEPT
#允许与目标地址10.0.0.4已经建立连接的机器通讯(用于响应包返回)

iptables -t filter -A FORWARD  -j REJECT
#最后拒绝所有


#web1访问web2被拒绝
ping 10.0.0.4
PING 10.0.0.4 (10.0.0.4) 56(84) bytes of data.
From 172.16.1.3 icmp_seq=1 Destination Port Unreachable
From 172.16.1.3 icmp_seq=2 Destination Port Unreachable

curl 10.0.0.4
curl: (7) Failed to connect to 10.0.0.4 port 80: 拒绝连接

#web2访问web1正常

ping 172.16.1.2
PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
64 bytes from 172.16.1.2: icmp_seq=1 ttl=63 time=0.721 ms
64 bytes from 172.16.1.2: icmp_seq=2 ttl=63 time=0.735 ms

curl 172.16.1.2
web1 website

NAT表

nat表: 负责网络地址转换,即来源与目的IP地址和port的转换。与主机本身无关,一般用于局域网共享上网或者特殊的端口转换服务相关。

nat表定义了四个链,nat功能就相当于网络的acl控制,和网络交换机acl类似

  • OUTPUT:和主机发出去的数据包有关,改变主机发出数据包的目标地

  • INPUT : 和主机J接收的数据包有关,改变主机发出数据包的目标地

  • PREROUTING:在数据包到达防火墙时进行路由判断之前执行的规则,作用是改变数据包的目的地址、目的端口等

  • POSTROUTING:在数据包离开防火墙时进行路由判断之后执行的规则,作用是改变数据包的源地址、源端口等

SNAT源地址转换

分类功能作用链
SNAT源地址转换出口POSTROUTING
SNAT选项
  • --to-source [ipaddr[-ipaddr]][:port[-port]]:修改源地址,也可以是轮询的地址范围

  • --random:请求时随机访问多个地址

  • --persistent:随机访问到一个地址后,之后始终用固定的地址访问

MASQUERADE 选项

地址伪装,此为动态SNAT,基于nat表中的Target,适用于动态IP

选项参数

  • --to-ports port[-port]

  • --random

实例:共享上网

环境准备

web1 主机 172.16.1.2 网关指向forward 172.16.1.3

forward 防火墙主机 10.0.0.3 172.16.1.3

开启linux转发方式

临时打开:
echo 1 > /proc/sys/net/ipv4/ip_forward
或
sysctl -w net.ipv4.ip_forward=1

永久打开:
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1         #将此行写入配置文件

sysctl -p                         #读取修改后的配置

配置SNAT

iptables -t nat -A POSTROUTING -s 172.16.1.2 -j SNAT --to-source 10.0.0.3
# 源地址为172.16.1.2的地址在转换为10.0.0.3
# 或者
iptables -t nat -A POSTROUTING -s 172.16.1.2 -j MASQUERADE

DNAT目标地址转换

分类功能作用链
DNAT目标地址转换进口PREROUTING

DNAT选项

  • --to-destination ipaddr[[-ipaddr][:port][-port]]

实例:(端口映射)web1访问防火墙主机172地址时转发到web2主机的80端口

环境

web1 主机 172.16.1.2

forward 防火墙主机 10.0.0.3 172.16.1.3

web2 主机 10.0.0.4 网关指向forward 10.0.0.3

开启linux转发方式

临时打开:
echo 1 > /proc/sys/net/ipv4/ip_forward
或
sysctl -w net.ipv4.ip_forward=1

永久打开:
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1         #将此行写入配置文件

sysctl -p                         #读取修改后的配置
iptables -t nat -A PREROUTING -i eth1 -d 172.16.1.3  -p tcp --dport 80 -j DNAT --to-destination 10.0.0.4:80
#当流量通过eth1进来且访问172.16.1.3的80端口是转发到10.0.0.4:80



curl 172.16.1.3(防火墙主机)
web2 website

REDIRECT 转发

redirect 通过改变目标ip和端口,将接收的包转发到同一个主机上的不同端口,可用于PREROUTING,OUTPUT链

REDIRECT选项

  • --to-ports port[-port]

示例:将本机的80端口转发到本机的81端口

iptables -t nat -A PREROUTING -d 10.0.0.4 -p tcp --dport 80 -j REDIRECT --to-ports 81