前言

表、链、规则

  • iptables 有四张表

    filter 用于过滤
    nat 用于网络地址转换
    mangle 用于给数据包做标记以修改分组数据的特定规则
    raw 表则独立于Netfilter连接跟踪子系统
  • iptables 命令在不显式指定表时,默认 filter 表
    iptables
  • iptables 3 种数据包经过的链(chain)
    chain.jpg
  • iptables 数据包详细走向图
    Tables_traverse.jpg

iptables 常见 target

ACCEPT      # 允许数据包通过
DROP        # 丢弃数据包
REJECT      # 拒绝数据包通过
SNAT        # 源地址转换
MASQUERADE  # 地址欺骗,自动化的snat
DNAT        # 目标地址转换
REDIRECT    # 重定向
LOG         # 将数据包信息记录到 syslog 日志
QUEUE       # 排队
RETURN      # 返回

iptables 防火墙为什么不占用端口?

  • 或许更准确的表述是:Linux 下 iptables 在做端口转发时为啥不占用端口?
  • 因为不占用端口,所以不能用 netstat 命令查看。
  • OSI模型与TCP/IP模型
    OSI模型与TCP/IP模型
  • iptables 工作在 OSI 模型的2/3/4层,做端口转发时,只需要查看和转换运输层的端口号,并不需要占用。以下摘自《计算机网络(第5版)》(谢希仁)175页。

    应当指出,从层次的角度看,NAPT 的机制有些特殊。
    普通路由器在转发 IP 数据报时,对于源 IP 地址或目的 IP 地址都是不改变的。但 NAT 路由器在转发 IP 数据报时,一定要更换其 IP 地址(转换源 IP 地址或目的 IP 地址)。
    其次,普通路由器在转发分组是,是工作在网络层。但NAPT 路由器还要查看和转换运输层的端口号,而这本来应当属于运输层的范畴。也正因为这样,NAPT 曾遭受一些人的批评,认为 NAPT 的操作没有严格按照层次的关系。

实例

  • 只允许 192.168.1.0/24 网段的 192.168.1.22 访问本机 6389 端口

    sudo iptables -I INPUT -s 192.168.1.0/24 -j DROP
    sudo iptables -I INPUT -s 192.168.1.22 -p TCP --dport 6389 -j ACCEPT
  • iptables 进行 url 过滤

    # iptables 其实不是真正对 url 进行过滤,只是对传送的数据包内容进行过滤
    # 而 http 头中含有目标 url
    # 关于 -m 参数,man iptables 只有几句简介,
    # 详细信息需要在 man iptables-extensions 里面进一步查询
    
    # 开启
    # 过滤掉含有 qq.com 的 url
    # ACCEPT 没用,因为 url 只在 http 头那个包
    sudo iptables -A OUTPUT -m string --string "qq.com" --algo bm -j DROP
    # 如果本机是 squid 服务器,可以通过 INPUT 链过滤
    sudo iptables -A INPUT -m string --string "qq.com" --algo bm -j DROP
    # 对于 nat 转发的内容过滤
    sudo iptables -A FORWARD -m string --string "qq.com" --algo bm -j DROP
    # 查看
    sudo iptables -nL --line-numbers
    # 移除(最后的数字为加 --line-numbers 参数后 num 显示的序号)
    sudo iptables -D OUTPUT 2
  • 移除过滤规则示例

    # 查看
    sudo iptables -t filter -nL --line-numbers
    # 移除。最后的数字为加 --line-numbers 参数后 num 显示的序号
    sudo iptables -t filter -D FORWARD 1
  • iptables限制同一 IP 连接数

    sudo iptables -I INPUT   -p tcp -j REJECT --reject-with tcp-reset -m connlimit --connlimit-above 20
    sudo iptables -I FORWARD -p tcp -j REJECT --reject-with tcp-reset -m connlimit --connlimit-above 10

端口转发

  • 监听本机 7777 端口,将数据转发到 192.168.7.8 的 8888 端口,实现 TCP 数据转发。
  • 以下步骤在 Ubuntu 18.04 下实测可用
  • 清空规则

    sudo iptables -F
    sudo iptables -X
    sudo iptables -t nat -F
    sudo iptables -t nat -X
    sudo iptables -t mangle -F
    sudo iptables -t mangle -X
    sudo iptables -P INPUT ACCEPT
    sudo iptables -P FORWARD ACCEPT
    sudo iptables -P OUTPUT ACCEPT
  • 开启端口转发(/etc/sysctl.conf)

    # 开启端口转发
    sudo sysctl net.ipv4.ip_forward=1
    # 查看
    sudo sysctl -a | grep ip_forward
  • 配置端口转发

    # 转发规则配置(可添加详细的限制规则)
    sudo iptables -t nat -A PREROUTING -p tcp --dport 7777 -j DNAT --to-destination 192.168.7.8:8888
    sudo iptables -t nat -A POSTROUTING -j MASQUERADE
    # 查看
    sudo iptables -t nat -nL
  • MASQUERADE 在 Ubuntu 18.04 下可能引起 dns 服务异常,参见 How to allow DNS lookup with iptables on Ubuntu 18.04 server,可改成如下配置:

    # tap0 为转发出口网卡代号
    # 本例 tap0 虚拟网卡
    iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE
    # OR (192.168.7.1 为虚拟网卡地址)
    iptables -t nat -A POSTROUTING -o enp4s0 -j SNAT --to-source 192.168.7.1
  • 移除示例

    # 查看
    sudo iptables -t nat -nL --line-numbers
    # 移除。最后的数字为加 --line-numbers 参数后 num 显示的序号
    sudo iptables -t nat -D POSTROUTING 1
  • 端口查看

    sudo netstat -anpt | grep 7777

    可以看到 iptables 端口转发的连接并不能用 netstat 查看,因为 NAPT 并不需要占用端口,7777 端口仍然可以被其它程序使用。若需查看,可使用netstat-natconntrack命令。

    sudo conntrack -L -p tcp --src-nat
    # OR
    sudo conntrack -L -n

备份与还原

  • 以下步骤在 Ubuntu 18.04 下实测可用
  • 可以用定时任务执行备份

    iptables-save > /home/qbit/iptables_rules_bak/iptables.rules
  • 以下重点讲开机自动还原
  • 创建文件

    /etc/systemd/system/rc-local.service
  • 在 rc-local.service 里面添加如下内容

    [Unit]
    Description=/etc/rc.local Compatibility
    ConditionPathExists=/etc/rc.local
    After=network.target
    
    [Service]
    Type=forking
    ExecStart=/etc/rc.local start
    TimeoutSec=0
    StandardOutput=tty
    RemainAfterExit=yes
    SysVStartPriority=99
    
    [Install]
    WantedBy=multi-user.target
  • 创建文件:/etc/rc.local 并添加如下内容

    #!/bin/bash
    /sbin/iptables-restore < /home/qbit/iptables_rules_bak/iptables.rules
    exit 0
  • 给 rc.local 添加可执行权限

    sudo chmod 754 /etc/rc.local
    # centos7
    sudo chmod 754 /etc/rc.d/rc.local
  • 启用服务(开机自启动)

    sudo systemctl enable rc-local
    # 等价于
    ln -s /etc/systemd/system/rc-local.service /etc/systemd/system/multi-user.target.wants/
  • 启动服务并检查状态

    sudo systemctl start rc-local.service
    sudo systemctl status rc-local.service
  • 重启服务器验证是否配置成功

Linux 历代防火墙

ipfwadm > ipchains > netfilter/iptables/ip6tables/arptables > nftables/nft
本文出自 qbit snap

qbit
268 声望279 粉丝