跳至内容

实验 8:iptables

目标

完成此实验后,您将能够

  • 配置基本的 IP 过滤规则
  • 配置 IP 转发

完成此实验的估计时间:60 分钟

我总是在我的 Linux 机器上使用 iptables。看——即使你不想阻止黑客,你也可以做一些事情,比如阻止像 *doubleclick.com 这样的广告网站和其他邪恶的混蛋。或者你可能只是想做更多的日志记录?…iptables 规则!

-- 乔治·W·布什

iptables

iptables 是一个用于管理 Linux 内核的 IPv4 数据包过滤和 NAT 子系统的工具。该子系统称为 netfilter。

iptables 命令行工具提供了用户空间的工具来管理该子系统。它用于设置、维护和检查内核中的 IP 数据包过滤规则表。可以定义多个不同的表。

iptables 讨论中使用的一些常用术语如下所述

表 (TABLES)

默认情况下,大多数 Linux 内核中定义了三个独立的表。任何时候存在的表都取决于内核配置选项和存在的模块。这些表是

  • filter: 这是主表,也是默认表(如果不传递 -t 选项)。它包含内置链

    • INPUT(用于进入本机的数据包)
    • FORWARD(用于通过本机路由的数据包)
    • OUTPUT(用于本地生成的数据包)。
  • nat: 当遇到创建新连接的数据包时,会查询此表。它包含以下三个内置链

    • PREROUTING(用于在数据包进入时进行修改)
    • OUTPUT(用于在路由之前修改本地生成的数据包)
    • POSTROUTING(用于在数据包即将外出时进行修改)
  • mangle: 此表用于专门的数据包修改。它有以下 5 个内置链

    • PREROUTING(用于在路由之前修改传入的数据包)
    • OUTPUT(用于在路由之前修改本地生成的数据包)
    • INPUT(用于进入本机的数据包)
    • FORWARD(用于修改通过本机路由的数据包)
    • POSTROUTING(用于在数据包即将外出时进行修改)

链 (CHAINS)

链是规则列表,可以匹配一组数据包。每条规则指定如何处理匹配的数据包。每个表包含多个内置链,并且还可以包含用户定义的链。

目标 (TARGETS)

防火墙规则指定数据包的标准,以及一个目标。如果数据包不匹配,则检查链中的下一条规则;如果匹配,则下一条规则由目标的值指定,该值可以是用户定义的链的名称,也可以是 ACCEPT、DROP、QUEUE 或 RETURN 等特殊值之一。

Usage: iptables -[ACD] chain rule-specification [options]
       iptables -I chain [rulenum] rule-specification [options]
       iptables -R chain rulenum rule-specification [options]
       iptables -D chain rulenum [options]
       iptables -[LS] [chain [rulenum]] [options]
       iptables -[FZ] [chain] [options]
       iptables -[NX] chain
       iptables -E old-chain-name new-chain-name
       iptables -P chain target [options]
       iptables -h (print this help information)

Commands:
Either long or short options are allowed.
  --append  -A chain Append to chain
  --check   -C chain Check for the existence of a rule
  --delete  -D chain Delete matching rule from chain
  --delete  -D chain rulenum
    Delete rule rulenum (1 = first) from chain
  --insert  -I chain [rulenum]
    Insert in chain as rulenum (default 1=first)
  --replace -R chain rulenum
    Replace rule rulenum (1 = first) in chain
  --list    -L [chain [rulenum]]
    List the rules in a chain or all chains
  --list-rules -S [chain [rulenum]]
    Print the rules in a chain or all chains
  --flush   -F [chain] Delete all rules in  chain or all chains
  --zero    -Z [chain [rulenum]]
    Zero counters in chain or all chains
  --new     -N chain Create a new user-defined chain
  --delete-chain
    -X [chain] Delete a user-defined chain
  --policy  -P chain target
    Change policy on chain to target
  --rename-chain
            -E old-chain new-chain
                Change chain name, (moving any references)

Options:
    --ipv4 -4 Nothing (line is ignored by ip6tables-restore)
    --ipv6 -6 Error (line is ignored by iptables-restore)
[!] --protocol -p proto protocol: by number or name, eg. `tcp'
[!] --source -s address[/mask][...]
        source specification
[!] --destination -d address[/mask][...]
        destination specification
[!] --in-interface -i input name[+]
        network interface name ([+] for wildcard)
 --jump -j target
    target for rule (may load target extension)
  --goto      -g chain
    jump to chain with no return
  --match -m match
    extended match (may load extension)
  --numeric -n numeric output of addresses and ports
[!] --out-interface -o output name[+]
    network interface name ([+] for wildcard)
  --table -t table table to manipulate (default: `filter')
  --verbose -v verbose mode
  --wait -w [seconds] maximum wait to acquire xtables lock before give up
  --line-numbers print line numbers when listing
  --exact -x expand numbers (display exact values)
[!] --fragment -f match second or further fragments only
  --modprobe=<command> try to insert modules using this command
  --set-counters -c PKTS BYTES set the counter during insert/append
[!] --version -V print package version.

练习 1

iptables 基础知识

本次实验将教你一些 iptables 的基础知识。特别是,你将学会如何查看或列出 iptables 规则,创建基本的过滤规则,删除规则,创建/删除自定义链等。

废话不多说,让我们直接开始使用 iptables

查看当前规则

  1. 以超级用户身份登录时,列出 filter 表中的所有规则。键入

    [root@serverXY root]# iptables -L
    
  2. 要查看更详细的输出,请键入

    [root@serverXY root]# iptables -L -v
    
  3. 仅显示 INPUT 链下的规则。键入

    [root@serverXY root]# iptables -v  -L INPUT
    
  4. 显示 mangle 表下的所有规则。键入

    [root@serverXY root]#  iptables  -L  -t   mangle
    
  5. 显示 nat 表下的所有规则。键入

    [root@serverXY root]# iptables -L -t nat
    

刷新所有当前规则

  1. 清除(或删除)所有“可能”当前已加载的规则。键入

    [root@serverXY root]# iptables --flush
    

创建自己的链

  1. 创建自己的自定义链并将其命名为“mychain”。键入

    [root@serverXY root]# iptables  -N  mychain
    
  2. 列出上面创建的链下的规则。键入

    [root@serverXY root]# iptables  -L mychain
    
    Chain mychain (0 references)
    
    target     prot opt source               destination
    

删除链

  1. 首先尝试删除内置的 INPUT 链。键入

    [root@serverXY root]# iptables -X INPUT
    

    问题

    你的输出是什么?

  2. 接下来尝试删除上面创建的链。键入

    [root@serverXY root]# iptables -X mychain
    
  3. 再次尝试列出刚刚删除的链中的规则。键入

    [root@serverXY root]# iptables -L  mychain
    

练习 2

基本数据包过滤

本次实验将教你如何编写更高级的数据包过滤规则。特别是,你将阻止来自你伙伴系统的所有 ICMP 数据包类型。

过滤 ICMP 数据包类型

  1. 开始之前,请确保你可以 ping 你的伙伴系统,并且你的伙伴系统也可以成功 ping 你。键入

    [root@serverXY root]# ping -c 2 serverPR
    
    <SNIP>
    
    --- serverPR ping statistics ---
    
    2 packets transmitted, 2 received, 0% packet loss, time 1005ms
    
    ...............................................
    
  2. 刷新你现有的所有规则。键入

    [root@serverXY root]# iptables -F
    
  3. 创建一个规则,阻止所有发往任何目的地的出站 icmp 类型数据包。键入

    [root@serverXY root]# iptables  -A  OUTPUT  -o  eth0 -p  icmp  -j  DROP
    

    用通俗易懂的语言来说,上一条命令可以解释为:“*向 filter 表中的 OUTPUT 链追加一条规则。让这条规则丢弃通过 eth0 接口出去的每一个 ICMP 类型的数据包*”

  4. 通过尝试 ping serverPR 来测试上面规则的效果。键入

    [root@serverXY root]# ping -c 2 serverPR
    
    PING serverPR (10.0.5.8) 56(84) bytes of data.
    
    ping: sendmsg: Operation not permitted
    
    ping: sendmsg: Operation not permitted
    
  5. 查看你刚刚创建的规则。键入

    [root@serverXY root]# iptables  -vL OUTPUT
    
    Chain OUTPUT (policy ACCEPT 21221 packets, 2742K bytes)
    
    pkts bytes target     prot   opt    in         out         source             destination
    
    93  7812 DROP     icmp    --  any         eth0    anywhere          anywhere
    
  6. 刷新所有规则,然后再次尝试从两个系统执行 ping 命令。

    问题

    成功还是失败?

  7. 现在创建一个新规则,该规则将丢弃来自特定不需要的 IP 地址(例如 172.16.0.44)的 icmp 数据包。键入

    [root@serverXY root]# iptables -A INPUT -i eth0 -p icmp --source 172.16.0.44 -j DROP
    

    你可以用通俗易懂的语言来理解上面的命令:*“向 filter 表中的 INPUT 链追加一条规则。让这条规则丢弃所有 ICMP 类型的数据包,并且源地址为 172.16.0.44”*

  8. 为了测试这条规则的效果,你可以请你实验室里任何一个没有被分配 172.16.0.44 IP 地址的人尝试 ping 你。成功还是失败?

  9. 与其刷新表中的所有规则,不如只删除上面创建的规则。要做到这一点,你需要知道规则的编号。要找出规则编号,请键入

    [root@serverXY root]# iptables -vL  INPUT --line-numbers
    
    Chain INPUT (policy ACCEPT 31287 packets, 9103K bytes)
    
    num   pkts  bytes   target        prot opt     in     out       source               destination
    
    1        486   40824  DROP       icmp --    eth0   any     serverPR             anywhere
    

    包含规则编号的列已在上面的示例输出中为你高亮显示。

  10. 使用你想要删除的规则所对应的行号,你可以通过运行以下命令来删除 INPUT 链中的特定规则(第 1 行)

    [root@serverXY root]# iptables -D INPUT 1
    

过滤其他类型的流量

本次实验你将学习如何过滤 tcp 类型流量。

流行的 ftp 协议是基于 TCP 的服务。这意味着它通过 TCP 类型的数据包传输。

在接下来的步骤中,我们将探索针对和过滤来自给定 IP 地址的 FTP 类型流量。

  1. 启动你在先前实验中配置并启用的 ftp 服务器。键入

    [root@serverXY root]# *service vsftpd restart*
    
    Shutting down vsftpd: [  OK  ]
    
    Starting vsftpd for vsftpd: [  OK  ]
    
  2. 请你的伙伴尝试匿名登录你的 ftp 服务器。在继续下一步之前,请确保你的伙伴能够成功从 serverPR 登录。

  3. 在你的伙伴仍然登录的情况下,创建一个规则来禁用来自 serverPR 的所有 ftp 类型流量。键入

    [root@serverXY root]# iptables -A INPUT -i  eth0 -s 172.16.0.z  -p tcp  --dport 21 -j DROP*
    

    用通俗易懂的语言来说,上面的规则/命令翻译为:*向 filter 表的 INPUT 链追加一条规则。让这条规则丢弃所有源地址为 172.16.0.z 且目的端口为 21 的数据包。*

  4. 当你执行上述命令后,netfilter 堆栈会立即生效。要查看这一点,请让你的伙伴在仍然登录到你的 ftp 服务器时尝试任何 ftp 命令——例如 `ls`。成功还是失败?

    实验任务

    成功还是失败?

    如果失败,请让你的伙伴尝试断开连接并重新登录,然后再次检查是否成功。

  5. 让你的伙伴以外的另一个人尝试匿名登录你的 ftp 服务器。你也可以请 hq.example.org 的某个人尝试连接你的 ftp 站点。

    问题

    成功还是失败?

  6. 在 serverXY 上启用并启动你的 web 服务器。

  7. 确保其他人可以使用浏览器访问你的网站。创建一个规则以阻止来自 hq.example.org 到你本地机器的 http 流量。

练习 3

基本数据包转发

本次实验你将学习如何设置基本的数据包转发规则。

你设置的规则将允许你的系统充当你伙伴系统的路由器。

你的系统将把所有源自你伙伴系统到互联网或你自己的默认网关的流量进行路由。这就是所谓的 IP 伪装或 NAT(网络地址转换)。

严格来说,IP 伪装和 NAT 是稍微不同的概念,并且通常用于实现不同的目的。在接下来的实验中,我们不会过多地讨论它们的具体区别。

本次实验将假定以下设置,请根据你的具体设置进行调整

ServerXY

i. 你的系统有两个网卡 - eth0 和 eth1。

ii. 第一个接口 eth0,将被视为外部接口(面向互联网)

iii. 第二个接口 eth1,将被视为内部接口(面向 LAN)

iv. 接口 eth0 的 IP 地址为 172.16.0.z

v. 接口 eth1 的 IP 地址为 10.0.0.z,子网掩码为 255.0.0.0

vi. 你已成功完成“实验 2”并理解了其中的基本概念。

ServerPR

以下是对你伙伴系统的假设。

i. 它只有一个网卡 - eth0

ii. eth0 的 IP 地址为 10.0.0.y,子网掩码为 255.0.0.0

iii. serverPR 的默认路由器或网关是 10.0.0.z(即 serverXY 的 eth1 的 IP 地址)

iv. 你已成功完成“实验 2”并理解了其中的基本概念。

将你的网络连接起来,使其看起来像下面所示的设置

上面,serverXY 和 serverPR 的常用图标已被路由器图标替换。

创建转发规则

  1. 确保你的网络物理连接如上图所示。

  2. 为所有接口分配适当的 IP 地址、子网掩码和网关设置。

  3. 刷新你当前加载的所有 iptables 规则。

    注意

    刷新表并非总是必需或强制性的。你可能已经注意到,在我们完成的某些实验的开头,我们都指定了刷新现有表。这是为了确保你从一个干净的状态开始,并且你的表中没有隐藏任何可能导致问题未按预期工作的错误规则。通常,你可以同时加载数百条规则,用于不同的功能。

  4. 请你的伙伴在 serverPR 上尝试 ping 172.16.0.100 (hq.example.org),这应该会失败,因为你现在充当 serverPR 的默认网关,并且你*尚未*在你的系统上启用任何路由。

  5. 在 serverXY 上以 root 用户身份键入

    [root@serverXY root]# *iptables --table  nat  -A  POSTROUTING -o eth0  -j  MASQUERADE*
    
  6. 现在重复第 4 步。

    问题

    你成功了吗?

  7. 上面的操作应该失败了。你还需要在你正在运行的内核中启用数据包转发。键入

    [root@serverXY root]#  *echo 1   >   /proc/sys/net/ipv4/ip_forward*
    
  8. 为了使上述更改在重启后对内核永久生效,请在你的 “/etc/sysctl.conf” 文件中创建以下条目

    net.ipv4.ip_forward = 0
    

保存 iptables 规则

到目前为止,你一直创建的所有 iptables 规则和链都是临时的或非永久的。这意味着如果你在任何时候必须重启你的系统,所有你所做的规则和更改都将丢失。

为了防止这种情况,你需要一种机制将临时的运行时 iptables 规则写入系统,以便它们在系统重启时始终可用。

  1. 使用 iptables-save 命令将所有更改保存到 /etc/sysconfig/iptables 文件。键入

    [root@serverXY root]# *iptables-save   >   /etc/sysconfig/iptables*
    

    技巧

    你在 iptables 中能做什么,仅受限于你的想象力。我们在本次实验中只触及了表面。希望我们已经触及了足够的表面,足以让你尽情发挥你的想象力。

额外加分项

以下是一些探索 iptables 的额外方法

问题和任务

  1. 要获得此命令 iptables -L -t nat 的更详细版本,需要哪个选项?

  2. 显示 OUTPUT 链下规则的命令是什么?

  3. ftp 服务“通常”在哪个端口上监听?

  4. 在 nat 表下创建名为“mynAT-chain”的链的命令是什么?

  5. 在线研究并列出一些更易于使用的工具或应用程序的名称,这些工具或应用程序可用于管理基于 Linux 的系统的防火墙子系统。

  6. 创建一个 iptables 规则来阻止来自 hq.example.org 到你本地机器的 http 流量。Web 服务器监听的知名端口是什么?写下实现此目的的完整命令?将上面写下的命令转换为其通俗易懂的等价物。

作者:Wale Soyinka