跳到主要内容

iptables

https://cycle.io/learn/iptables-advanced

https://gist.github.com/nerdalert/a1687ae4da1cc44a437d

https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture

https://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands

netfilter:hook 回调框架.

iptables:防火墙配置软件, 底层使用 netfilter。

  1. PRE_ROUTING 路由查找之前
  2. LOCAL_IN 目标地址是本机
  3. FORWARD 目的地是其他网络节点
  4. LOCAL_OUT 出站
  5. 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 进行伪装。

MasqueradingSNAT 的更智能的形式。(会将源 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

图解

这个图片中有三条线路

  1. network -> prerouting(nat) -> routing -> input -> host(app)
  2. host(app) -> output(filter,nat) -> postrouting(nat) -> network
  3. network -> routing -> forward -> postrouting -> network

从 routing 处会分叉

  1. 目标地址是本机上的应用,会转到 INPUT
  2. 目标地址非本机,会转到 FORWARD。 (本机作为中转)

https://cloud.githubusercontent.com/assets/1711674/8742362/87fa6654-2c32-11e5-84d6-3ca58dda0a8d.png