iptables简介(二)
浏览 275 | 评论 0 | 字数 6796
lovecatc
2020年09月26日
  • 本篇文章参考了iptables tutorial

    Part 0

    iptables工作在网络层和传输层。这意味着它虽然可以处理应用层的一些问题,但你不应这样做。iptables应该只处理数据包的头部,而不触及实际的数据部分。
    ICMP包用于错误报告,它的头部包括了IP,但是它实际上是IP协议的一部分,而非IP协议的上层协议。
    iptables属于IP filter。一个实现严格的IP filter应该只工作在IP协议上,即它只能通过IP的头部来进行工作。然而iptables并不是严格的IP Filter。因此它还能够根据TCP/UDP类型、MAC等等协议工作。

    Part 1 Table

    Mangle table

    mangle表支持以下的targets:

    • TOS(Type Of Service)
      用于更改数据包的TOS。
    • TTL
      用于更改数据包的TTL(Time To Live)。
    • MARK
      用于为数据包添加标记,这些标记后续可以被iproute2项目处理。
    • SECMARK
      用于为数据包设置安全字段,以在SELinux中处理。
    • CONNSECMARK
      用于复制安全字段。

    NAT table

    注意,对于NAT table,每个数据流中只有第一个数据包才会被此表处理。之后剩余的数据包会自动按第一个数据包的方式被处理。

    • DNAT
      用于更改数据包的目标地址。
    • SNAT
      用于更改数据包的源地址。
    • MASQUERADE
      与SNAT相似。但是对DHCP有更好的支持,而非如SNAT只能转换固定的IP。
    • REDIRECT

    Raw table

    • NOTRACK
      用于设置不需要被connect tracking system跟踪的数据包。

    Filter table

    • ACCEPT
    • DROP

    Part 2 the State Machine

    iptables的状态机实际上就是其connection tracking system。数据包共有4个状态,NEW, ESTABLISHED, RELATED, INVALID
    当本机发出一个数据包时,它在OUTPUT被标记为NEW。如果本机之后收到了一个返回的数据包,那么这个数据包对应的连接在PREROUTING被置为ESATABLISHED。如果第一个包不是本机产生的,那么置NEW的过程也在PREROUTING完成。
    如果一个连接是在ESTABLISHED流的基础上建立的,那么它就被标记为RELATED。例如FTP的数据流就是建立在FTP的控制流的基础上的。
    INVALID则标注了那些无法辨识属于哪个连接或是没有任何状态的数据包。
    如果数据包在raw上被标注NOTRACK,那么它不被跟踪。

    Part 3 command

    # 导出目前的iptables配置
    # iptables-save [-c] [-t table]
    sudo iptables-save -c > ./iptables.save.txt
    
    # 恢复iptables配置
    # iptables-restore [-c] [-n]
    sudo iptables-restore -c < ./iptables.save.txt

    一般的iptables配置语句如下

    iptables [-t table] command [match] [target/jump] 

    table

    如果不显式指定-t的参数,那么将会使用filter表。
    可以选用的表前文已经说明,即

    • nat
    • mangle
    • filter
    • raw

    command

    • append
      -A --append,在链的结尾添加一条规则。

    例如iptables --append INPUT

    • delete
      -D --delete,删除链中的一条规则。既可以通过规则匹配删除,也可以通过序号删除。

    例如iptables --delete INPUT --dport 80 -j DROP,此为规则匹配删除;
    iptables --delete INPUT 1,此为序号匹配删除。

    • replace
      -R --replace,替换链中指定序号的规则。

    例如iptables --replace INPUT 1 --dport 80 -j DROP

    • insert
      -I --insert,在链中指定序号的位置插入规则。

    例如iptables --insert INPUT 1 --dport 80 -j DROP

    • list
      -L --list,显示相应链中所有的规则。不显式指定操作的链将显示对应中所有的链。

    例如iptables --list INPUT

    • flush
      -F --flush,清空指定链中的所有规则。不显式指定链将清空对应表中在所有链中的规则。

    例如iptables --flush INPUT

    • zero
      -Z --zero,将链上的数据包计数器清零。

    例如iptables --zero INPUT

    • new-chain
      -N --new-chain,创建一条新链。

    例如iptables --new-chain allowed

    • delete-chain
      -X --delete-chain,删除一条链。被删除的链中不能含有规则。

    例如iptables --delete-chain allowed

    • policy
      -P --policy,为一条链设置默认的target。一般的target包括DROPACCEPT

    例如iptables --policy INPUT DROP

    • rename-chain
      -E --rename-chain,重新命名一条链。

    例如iptables --rename-chain allowed permitted

    option

    • verbose
      -v --verbose,显示详细输出,一般与-L连用。

    它支持与--list --append --insert --delete --replace连用。

    • exact
      -x --exact,显示精确值(byte)而非MB/GB。只能与-L连用。
    • numeric
      -n --numeric,显示ip地址和端口而非主机名或网络应用名。只能与-L连用。
    • line-numbers
      --line-numbers,在打印规则时显示序号。只能与-L连用。
    • set-counters
      -c --set-counters,设置数据包和字节计数器。例如--set-counters 40 2000将设置包计数器为40,字节计数器为2000。与--insert --append --replace连用。
    • modprobe
      --modprobe,添加模块。

    match

    Generic match

    • protocol
      -p --protocol,指定要处理的数据包协议类型。常见的类型包括TCP, UDP, ICMP。事实上,可以使用/etc/protocols中的协议及其代码来指定。
    • source
      -s --src --source,指定源IP地址。此种方式即可以指定单个ip,也可以指定CIDR形式的ip段,如192.168.1.0/24。此外,还可以写作192.168.1.0/255.255.255.0。通过--source ! 192.168.1.1,可以匹配除192.168.1.1以外的ip。
    • destination
      -d --dst --destination,指定目标IP地址。与source工作方式相似。
    • in-interface
      -i --in-interface,指定包入境时通过的网络接口。只能在INPUT, FORWARD, PREROUTING中使用。可以使用eth+这种方式指定所有的eth接口。
    • out-interface
      -o --out-interface,指定出境时通过的网络接口。只能在OUTPUT, FORWARD, POSTROUTING中使用。使用方法和--in-interface类似。
    • fragment
      -f --fragment,匹配一个分段包的剩余部分(即非头包)。使用!时,应像这样使用:! --fragment

    Implicit matches

    为了使用这些match规则,需要显式指定匹配的协议,如tcp matches必须显式指定-p tcp

    TCP match
    • source-port
      --sport, --source-port,指定数据包的源端口。也可以通过指定service name但这样会拖慢匹配速度。可以通过--sport 22:80这种方式来指定22到80之间的所有端口。缺省前一个端口会默认使用0,即:80等价于0:80;缺省后一个端口则默认使用65535,即22:等价于22:65535。同样,可以使用--sport ! 80这种用法。
    • destination-port
      --dport, --destination-port,指定数据包的目标端口。用法与--source-port类似。
    • tcp-flags
      --tcp-flags,用于匹配TCP报的标志字(flag)。支持的标志字包括SYN, FIN, ACK, RST, URG, PSH。还可以使用特殊字ALL, NONE
    • tcp-option
      --tcp-option,用于匹配TCP头的特殊部分。
    UDP match
    • source-port
      与TCP中相同内容的工作方式相同。
    • destination-port
      与TCP中相同内容的工作方式相同。

    省略ICMP和SCTP的配置部分。详细内容可以在篇首的参考文章中找到。

    Explicit match

    此匹配需要显式以-m --match指定以匹配。由于内容过多,仅摘录部分日常使用的选项。详细的内容请参考篇首的文章。

    IP range match
    • src-range
      形如iptables -A INPUT -p tcp -m iprange --src-range 192.168.1.13-192.168.2.23。它匹配一组范围内的源IP地址。也同样支持!的使用。
    • dst-range
      与以上源IP的使用类似。
    Multiport match
    • source-port
      形如iptables -A INPUT -p tcp -m multiport --source-port 22,53,80,110
    • destination-port
      用法与--source-port类似。
    • port
      用法与--source-port类似。注意此选项仅用于src和dst端口相同的数据包。

    target and jump

    target

    仅列举常见选项。

    • ACCEPT
      -j ACCEPT,被ACCEPT的包不会再在当前chain或当前table中的其它chain被传递而直接被接受。
    • DNAT
      -j DNAT --to-destination ip[:port],DNAT target仅在NAT表中的PREROUTINGOUTPUT链中可用。

    在继续介绍其它的target之前,我们首先考虑DNAT的一个问题。
    考虑这样一个情景。现在有一台位于内网的http服务器,内网地址为$HTTP_IP,服务器的防火墙有外网IP$INET_IP,内网IP$LAN_IP。位于外网的客户机IP为$EXT_BOX想要访问服务器,于是考虑在防火墙上使用iptables转发,命令如下。

    iptables -t NAT -A PREROUTING --dst $INET_IP --dport 80 -j DNAT --to-destination $HTTP_IP 

    对于一台公网客户机,此配置是合理的。但是考虑这样一个情景。一台与服务器在同一个内网的客户机访问服务器。假设内网机器IP为$IN_BOX。此时从内网机器发出的数据包以dst=$INET_IP试图从公网访问http服务器。数据包在防火墙处被DNAT,并成功转发给http服务器。然而,http服务器试图发送一个返回的数据包时,它的路由表最终会指出客户端与它位于同一个网络下,于是http服务器将直接指定返回的数据包dst=$IN_BOX并发送。而对于客户端来说,它发送的数据包为dst=$INET_IP,但是返回的数据包却是src=$HTTP_IP。于是这个返回的数据包就被丢弃。客户端永远得不到一个“真正”的返回数据包。

    SNAT可以用来解决这个问题。显然,上述问题的出现原因在于内网机器通信时数据包不经过网关(防火墙)。因此在数据包入境时利用SNAT,将src设置为网关的内网IP$LAN_IP。如此,数据包返回时必然会经过网关,再在网关处deSNAT, deDNAT即可。命令如下

    iptables -t NAT -A POSTROUTING --dst $HTTP_IP --dport 80 -j SNAT --to-source $LAN_IP

    结束了吗?不妨再考虑,防火墙本身要访问http服务器是什么情况。很显然,会再次发生以上情况。因此,还需要进行output链上的DNAT配置

    iptables -t NAT -A OUTPUT --dst $INET_IP --dport 80 -j DNAT --to-destination $HTTP_IP

    以上案例说明了两个问题。首先在设置规则时要特别小心,考虑所有的情况;此外,在网关处SNAT、DNAT的数据包,对应连接返回的数据包会被自动转换回原本的地址。这要归功于connection tracking system。

    • DROP
      直接丢弃数据包且不返回任何信息。
    • REJECT
      和DROP相似,但是会返回错误信息。只在INPUT、FORWARD和OUTPUT链中合法。
    • RETURN
      使数据包停止在当前链中的规则匹配,并应用默认规则。如果是子链,则返回到主链。
    • SNAT
      与DNAT相似,用法为iptables -t NAT -A POSTROUTING -p TCP -j SNAT --to-source 192.168.1.123

    Part 4 Debug

    善于利用定时任务crontab。在/etc/crontab中配置。命令例如

    */5 * * * * /etc/iptables/flush.sh stop

    待续...(咕)

    本文作者:lovecatc
    本文链接:https://lovecatc.com/index.php/archives/25/
    最后修改时间:2020-09-26 07:35:47
    本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!
    评论
    与本文无关评论请发留言板。请不要水评论,谢谢。
    textsms
    支持 Markdown 语法
    email
    link
    评论列表
    暂无评论