1. Iptables 简介
-
iptables
是防火墙吗 ?iptables 其实不是真正的防火墙,我们可以把它理解成一个客户端代理,用户通过iptables这个代理,将用户的安全设定执行到对应的"安全框架"中,这个"安全框架"才是真正的防火墙,这个框架的名字叫
netfilter
。后面会陆续推出使用golang调用netfilter
和netlink
两个网络库的参考代码,有兴趣的可以点下关注;
1.1 IPtables核心概念之四表
表(table)是存储规则包规则的地方,类似于路由器存储路由表; 表是作用在链路节点上。
- filter表:INPUT,FORWARD,OUTPUT (过滤数据)
- nat表:PREROUTING,POSTROUTING INPUT OUTPUT (端口和地址映射,数据转发)
- mangle表:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING 修改数据包的TOS(Type of Service,服务类型)等
- raw表:PREROUTING,OUTPUT 设置raw时一般是为了不再让iptables做数据包处理
表的处理优先级:raw > mangle > nat > filter
1.2 IPtables核心概念之五链
链(chan)是包经过的路线,可以理解成包在系统中的一个生命周期需要经历的hook;
- PREROUTING: 处理进来的包,等待路由决策
- POSTROUTING: 路由决策之后,向外发送的数据包
- INPUT: 外部进来的包,已经做完路由决策,发往本机的数据包
- FORWARD: 外部进来的包,路由决策之后,需要转发的包.
- OUTPUT: 本机产生需要向外部发送的数据包(未经路由决策);
1.3 一图胜千言
- 上层协议栈指的是用户空间
- 非本地IP需要经过FORWARD链转发时许开启linux转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
;
2. 常用命令介绍及用途解析
2.1 Filter 表 Input 链
- 基本操作
# 默认显示的就是filter表 > iptables -nvL # 查询filter表的链规则,并显示规则号码 > iptables -t filter -nvL --line Chain INPUT (policy ACCEPT 120K packets, 244M bytes) num pkts bytes target prot opt in out source destination 1 369K 111M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 /* test */ Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 376K packets, 202M bytes) num pkts bytes target prot opt in out source destination Chain CUSTOM_CHAIN (0 references) num pkts bytes target prot opt in out source destination # 删除INPUT Chan的策略 > iptables -t filter -D INPUT 1
- 禁止与开放一条链(勿对
INPUT
链进行操作)# 禁止FORWARD链 > iptables -t filter -P FORWARD DROP # 开启FORWARD链 # 需一同开启linux内核转发功能, echo 1 > /proc/sys/net/ipv4/ip_forward > iptables -t filter -P FORWARD ACCEPT
- 插入一条规则到filter表的INPUT链
- -p,--protocol [tcp|udp|icmp] 不同的协议有不同的参数如tcp有,--sport,--dport,--tcp-flags, --src, --dst 等。
- -j,--jump [ACCEPT|DROP|REJECT|RETURN|DNAT|SNAT|MASQUERADE|CUSTOM_CHAIN] 目标动作或跳转到对应链
- -A,--append 追加规则(规则是从上往下匹配)
- -I,--insert 默认从1号插入,可以知道号码
# 开放目标端口 3306 > iptables -t filter -I INPUT -p tcp --dport 3306 -j ACCEPT # 开放目标端口 3000:3306 > iptables -t filter -I INPUT -p tcp --dport 3000:3306 -j ACCEPT # 禁用来源192.168.0.0/24的网段对3306发起TCP链接 # tcp-flasg SYN,FIN,ACK 因为tcp需要发起tcp syn包进行链接 > iptables -t filter -I INPUT -p tcp -s 192.168.0.0/24 --dport 3306 --tcp-flags SYN,FIN,ACK -j DROP # 为规则加备注 > iptables -t filter -I INPUT -p tcp --dport 3306 -m comment --comment "mysql" -j ACCEPT # 数据包用户空间的状态匹配 # 留存现有访问3306端口的链接,禁止新链接访问3306端口 > iptables -t filter -A INPUT -p tcp --dport 3306 -m state --state ESTABILISHED,RELATED -j ACCEPT > iptables -t filter -A INPUT -p tcp --dport 3306 -m state --state NEW -j REJECT
- DROP 与 REJECT 的区别
# 直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求入海了,过了超时时间才会有反应。 > iptable -t filter -I INPUT -p tcp --dport 3306 -j DROP # 拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。 > iptable -t filter -I INPUT -p tcp --dport 3306 -j REJECT
- REJECT 可选的返回响应,
icmp-net-unreachable
icmp-host-unreachable
icmp-port-unreachable
icmp-proto-unreachable
icmp-net-prohibited
icmp-host-prohibited
tcp-reset
port-unreachable(默认响应)
> iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
- REJECT 可选的返回响应,
2.2 Nat 表 PreRouting / PostRouting 链
-
PreRouting / PostRouting 这两个链一般在防火墙上是非常常见。它们对应的场景如,包从外网进入内网,包从内网出外网,包从内网到内网的不同网段;
-
示例一
- 源地址(外网):111.1.1.1
- 目标服务器(内网): 192.168.1.2:3306
- 防火墙(内外网): eth0(111.1.1.2), eth1(192.168.1.1)
# 开启转发,因为要把包的dst地址改变成非我们防火墙本机的地址 > echo 1 > /proc/sys/net/ipv4/ip_forward > iptables -t filter -P FORWARD ACCEPT # [包从外网进入内网] # 111.1.1.1 访问内网的目标服务器 192.168.1.2:3306 # 把包的目标地址改成内网的地址 192.168.1.2 > iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 3306 -j DNAT --to-destination 192.168.1.2:3306 # [包从内网出外网] # 当目标服务响应后,想回包到外网 111.1.1.1。 # 假设目标服务器的网关是我们本机的防火墙的内网地址 192.168.1.1,所以包会经过我们再回到外网 111.1.1.1 # -d ! 192.168.0.0/24 , 表明目标地址非192.168.0.0/24网段的包 > iptables -t nat -A POSTROUTING -i eth1 -d ! 192.168.0.0/24 -p tcp --sport 3306 -j SNAT --to-resource 111.1.1.2
-
示例二
- MASQUERADE 伪装一个连接意味着,我们自动获取网络接口的IP地址,而不使用--to-source。在动态的DHCP和拨号上网时有很好的效果。
# 从eth0出去的包的源地址会伪装成eth0上的地址 > iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-
说一个我困惑的知识点: 按照我以往的认识,认为回包的流量应该先后经过OUTPUT和POSTROUTING,所以我利用iptables -t nat -nvL去查看NAT表在OUTPUT链和POSTROUTING链上的packge计数器,结果发现没有上涨。最后寻找到一个解析,下面描述下大概意思。
- NAT表只在连接状态是NEW的时候(也就是TCP的第一个握手包)才会执行计算,一旦改写关系存入了conntrack,那么这条连接后续的通讯就不会再过POSTROUTING和OUTPUT上面的NAT表了,而是直接换成了匹配conntrack来复原连接之前的改写状态。
2.3 Filter表 Forward 链
-
一般不属于自身的IP但需要转发到别的目标,必要时还需要配合nat表进行改变目的地址或者源地址。
# 如10.8.0.2 需要访问 192.168.0.2 (eth0: 192.168.0.1) # 转发 10.8.0.0/24 网段的ip > iptables -A FORWARD -s 10.8.0.0/24 -j ACCEPT > iptables -t nat -A POSTROUTING -p tcp -d 192.168.0.0/24 -j SNAT --to-source 192.168.0.10
# 如 192.168.0.2 需要访问 10.8.0.2(eth1: 10.8.0.1) # 转发 192.168.0.0/24 网段的ip > iptables -A FORWARD -s 192.168.0.0/24 -j ACCEPT > iptables -t nat -A POSTROUTING -p tcp -d 10.8.0.0/24 -j SNAT --to-source 10.8.0.1
3. 一些场景
3.1 自定义链
- 自定义链是用于方便管理一类业务的网络规则;
# 在filter表中创建自定义链 > iptables -t filter -N CUSTOM_CHAIN # 建立自定义链规则,开放22端口 > iptables -t filter -I CUSTOM_CHAIN -p tcp --dport 22 -j ACCEPT # 查看规则 > iptables -t filter -nvL CUSTOM_CHAIN --line Chain CUSTOM_CHAIN (0 references) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 # 在INPUT 链中引用自定义链规则,让目标端口是22的包jump to CUSTOM_CHAIN链 > iptables -t filter -I INPUT -p tcp --dport 22 -j CUSTOM_CHAIN # 修改链名字 > iptables -E CUSTOM_CHAIN NEW_CUSTOM_CHAIN # 删除自定义链: 1. 链没有被引用; 2. 链中没有任何规则 > iptables -X NEW_CUSTOM_CHAIN
3.2 负载均衡
-
-m 使用扩展模块statistic(是一个统计模块)支持random 和nth 两种模式,这里仅介绍random模式
-
示例一
# 计算公式 # probability 设置概率 # probability =1/(n−i+1) # n: 后端数量 # i: 序号(从1)开始 # 访问 192.168.29.135:80 随机分发到 192.168.29.135:90-91 > iptables -A PREROUTING -t nat -p tcp -d 192.168.29.135 --dport 80 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 192.168.29.135:9090 > iptables -A PREROUTING -t nat -p tcp -d 192.168.29.135 --dport 80 -m statistic --mode random --probability 1 -j DNAT --to-destination 192.168.29.135:9091
-
示例二
# 使用mark 进行ip包打标识 > iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1 # 通过匹配 mark 标识来匹配并进行负载均衡 > iptables -t nat -A PREROUTING -m mark --mark 1 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 192.168.29.135:9090 > iptables -t nat -A PREROUTING -m mark --mark 1 -m statistic --mode random --probability 1 -j DNAT --to-destination 192.168.29.135:9091
3.3 限制流量
- -m limit
# 限制3306端口的包的数量,限制100个包,100 * 1500Bytes / 1024 = 146KB/s > iptables -A INPUT -m limit -p tcp --dport 3306 --limit 100/s # --limit-burst 是最大的包数量 > iptables -A INPUT -m limit -p tcp --dport 3306 --limit-burst 1000
3.4 限制链接
- -m connlimit 限制链接数
# --connlimit-above n 限制为多少个 # --connlimit-mask n 掩码,默认是connlimit-mask 32 ,即每个IP如设置为0 那就是所有客户端只能连 n个 # --reject-with 也可以尝试 icmp-host-unreachable 、icmp-port-unreachable > iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT --reject-with tcp-reset
4.参考
- iptables www.frozentux.net/iptables-tu…
5.写在最后
- 您都看到这了,给个赞👍再走吧;