netfilter/iptables 笔记

7 minute read

netfilter 与 iptables

netfilter是linux默认的防火墙,在2.4之后的版本正式进入内核。netfilter 使用四个表(Table)来存放控制信息包过滤处理的规则集。每张表由链(Chain)组成,每条链又包含了多条规则(rule)。

iptables是用来编辑操作这些表的一个工具。iptables包中也包含了针对IPv6的工具ip6tables

四个表及其包含的链:

  • filter
    • INPUT
    • FORWARD
    • OUTPUT
  • nat
    • PREROUTING
    • POSTROUTING
    • OUTPUT
  • mangle
    • PREROUTING
    • INPUT
    • FORWARD
    • OUTPUT
    • POSTROUTING
  • raw
    • PREROUTING
    • OUTPUT

img

filter机制

filternetfilter中最重要的机制,其任务是执行数据包的过滤操作。具有三种内建链:

  • INPUT - 来自外部的数据包(访问本机)
  • OUTPUT - 发往外部的数据包(本机访问外部)
  • FORWORD - “路过”本机的数据包,转发到其他设备

链中规则的匹配方式遵循first matchfilter会根据数据包特征从相应链中的第一条规则开始逐一进行匹配。只要遇到满足特征的规则后便不再继续。 每条链在最底端都定义了默认规则。默认规则只会有一种状态:ACCEPT或者DROP。默认为ACCEPT

iptables命令参数

格式:

iptables -操作方式 [链名] [条件匹配] [选项]

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)

常用操作方式:

  • -L(--list) [chain] 列出所有规则或指定链的规则
  • -A(--append) chain 在指定链中添加新规则
  • -C(--check) chain 检查规则是否存在
  • -D(--delete) chain rule_num 删除链中匹配的规则
  • -F(--flush) [chain] 清除指定链或者全部链中的规则
  • -P(--policy) chain 设置指定链的默认策略
  • -R(--replace) chain rule_num 替换指定链中特定行的规则,第一行行数为1

常用选项:

  • -p(--protocol) proto 指定协议,如tcp udp icmp
  • -j(--jump) target 规则的目标(??),如ACCEPT DROP REJECT
  • -s(--source) address[/mask] 数据包源IP,可为单IP或CIDR网段或域名
  • -d(--destination) address[/mask] 数据包目的IP,可为单IP或CIDR网段或域名
  • --dport port 目的端口,必须指明-p
  • --sport port 来源端口,必须指明-p
  • --line-numbers 显示行号

关于-p配置的上层协议,可参考/etc/protocols

state模块

state模块实现了“连接跟踪”功能,用来解决某些情况下防火墙内主机对外建立链接的问题。 state模块定义了四种数据包链接状态,分别为ESTABLISHED NEW RELATED INVALID 四种。在TCP/IP标准的定义中,UDP和ICMP数据包是没有链接状态的,但是在state模块的定义中,任何数据包都有连接状态。

ESTABLISHED状态

只要数据包能够成功穿过防火墙,则之后的所有数据包(包括响应数据包)都会被标记为是ESTABLISHED状态。

当我们设置防火墙INPUT链的默认策略为DROP时,防火墙内主机很多服务,如ssh客户端基本上就无法与外面的ssh服务端建立连接了。原因很简单,ssh客户端使用的端口是随机的,防火墙无法预知客户端会使用哪一个端口发起链接。因此即使客户端发出了请求,ssh服务端返回的相应数据包也会被防火墙的默认策略拦截。

ESTABLISHED状态可以很轻易的解决此问题,见#解决应用程序无法从防火墙主机上对外建立新连接的问题

NEW状态

每一条链接中的地一个数据包的状态定义为NEW

RELATED状态

RELATED状态的数据包其含义是指,被动产成的应答数据包,且此数据包不属于当前任何链接。换一种说法就是,只要应答的数据包是因为本机发起的连接送出vhu一个数据包,导致了另一条连接的产生,那么这个新连接的所有数据包都属于RELATED状态。

以ubuntu上上的tracepath工具为例,在检测本机与目的主机间跳数时,tracepath是通过发送TTL值从1递增的tcp数据包来检测每一跳。路径中的路由器因TTL减为0而回送了一个ICMP数据包(ICMP Type 11),该数据包就属于RELATED状态。

INVALID状态

INVALID状态指的是状态不明的数据包,即不属于ESTABLISHED NEW RELATED三种类型的数据包。所有的INVALID数据包都应该视为恶意数据包。

实例

丢弃icmp协议包(禁止ping)

通过此规则实现禁止ping本机的效果

iptables -A INPUT -p icmp -j DROP

解决应用程序无法从防火墙主机上对外建立新连接的问题

iptables -A INPUT -p tcp -m state ESTABLISHED -j ACCEPT