iptables
https://cycle.io/learn/iptables-advanced
https://gist.github.com/nerdalert/a1687ae4da1cc44a437d
netfilter:hook 回调框架.
iptables:防火墙配置软件, 底层使用 netfilter。
- PRE_ROUTING 路由查找之前
- LOCAL_IN 目标地址是本机
- FORWARD 目的地是其他网络节点
- LOCAL_OUT 出站
- POST_ROUTING 路由之后
nftables, eBPF
INPUT
OUTPUT
FORWARD
tables
Filter table (默认)
- input 进入防火墙
- output 出防火墙
- forward 转发到其他网络(通过本机路由的数据包)
NAT table
- PREROUTING 在路由前修改数据包。(进入系统之后,路由之前) DNAT(目标网络地址转换)
- POSTROUTING 在路由之后修改数据包。(数据包离开系统时)SNAT(源网络地址转换)
- OUTPUT 防火墙本地生成数据包的 NAT 转换
Manage table
修改 tcp 报文的头部
- PREROUTING
- OUTPUT
- FORWARD
- INPUT
- POSTROUTING
不常用的 tables
- raw table
- security table
高级 NAT 配置
伪装源IP (SNAT)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
对网卡 eth0 出去的流量的 源 IP 进行伪装。
Masquerading 是 SNAT 的更智能的形式。(会将源 ip 改为出口网卡的有效IP)
端口转发
将访问本机 8080 端口的请求转发到 192.168.1.100:80
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
-t nat 指定 nat 表
-A PREROUTING 指定 PREROUTING 链
-p tcp --dport 8080 触发条件
-j DNAT 要执行的动作
--to-destination 192.168.1.100:80 将目标地址改为 192.168.1.100:80
NAT 负载均衡
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 192.168.1.101:80
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -m statistic --mode nth --every 2 --packet 1 -j DNAT --to-destination 192.168.1.102:80
-m statistic --mode nth --every 2
-m statistic调用 statistic 模块--mode nth指定 statistic 的模式, nth 表示按顺序数数--every 2指定计数的周期,每 2 个包为一轮,包满了则清零计数。 --packet 0 -j DNAT --to-destination 192.168.1.101:80 包1 转发到 192.168.1.101:80 --packet 1 -j DNAT --to-destination 192.168.1.101:80 包2 转发到 192.168.1.102:80
允许已建立和相关链接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
丢弃无效数据包
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
限制 ssh 尝试连接次数
每分钟最多 5 次
sudo iptables -A INPUT -p tcp --dport 22 -m limit --limit 5/min -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP
限制 ICMP 流量
ping 请求 1s 一次
sudo iptables -A INPUT -p icmp -m limit --limit 1/sec -j ACCEPT
sudo iptables -A INPUT -p icmp -j DROP
使用脚本管理 iptables
封锁在 600 秒(10 分钟)内尝试 10 次 SSH 登录失败的 IP 地址。
#!/bin/bash
# Simple script to block an IP address after 10 failed SSH login attempts
iptables -N SSH_BLACKLIST
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 600 --hitcount 10 --name SSH -j SSH_BLACKLIST
iptables -A SSH_BLACKLIST -j LOG --log-prefix "SSH Blacklist: "
iptables -A SSH_BLACKLIST -j DROP
iptables 的备份与恢复
备份
iptables-save > /etc/iptables/rules.v4
恢复
iptables-restore < /etc/iptables/rules.v4