1. 补充一些基本概念
	1.1 OSI开放系统互联7层模型
	1.2 IPv4地址
2. iptables
	2.1 iptables 语法
	2.2 filter表对规则链的操作
	2.3 filter表对规则的操作
	2.4 filter表的基本匹配操作
3. 其他filter表匹配操作
	3.1 tcp filter表匹配操作
	3.2 udp filter表匹配操作
	3.3 icmp filter表匹配操作
4. filter 表目标扩展
5. filter 表匹配扩展
	5.1 multiport
	5.2 limit
	5.3 state
	5.4 mac
	5.5 owner
	5.6 mark
	5.7 tos
	5.8 addrtype
	5.9 iprange
	5.a length
	5.b. conntrack
6 简单防火墙
	6.1 准备
	6.2 一台机器的防火墙
	6.3 临时许可某端口

 

 

1. 补充一些基本概念

1.1 OSI开放系统互联7层模型

  • 7 应用层 软件:界面
  • 6 表示层 软件:加密/解密
  • 5 会话层 软件:
  • 4 传输层系统:端口TCP/UDP
  • 3 网络层硬件:路由器IP/ICMP
  • 2 链路层硬件:网卡MAC
  • 1 物理层硬件:网线

一些名词

  • 面向连接协议: TCP
  • 无连接协议: UDP, IP
  • ICMP: 控制报文协议 (Internet Control Message Protocol) 主要用于ping
  • UDP: 用于DNS查询, SNMP(简单网络管理协议), RADIUS(远程用户拨号认证系统)等
  • MAC(48bit): Media Access Control 介质访问控制
  • ARP: 地址解析协议 Address Resolution Protocol 用于关联一个物理设备网卡和IP, $ cat /proc/net/arp

1.2 IPv4地址

IPv4 共32位: 4 * 8 bit; 总共约40亿, 减去私有地址和D,E类, 只有约30亿. 
但由于NAT技术, 使得私有地址可以反复无限制的使用, 使得IP总数成为无限... 
但是增加的网络复杂程度.出错率.损失了网速.
IPv6 共128位: 8组冒号分隔的十六进制表示. 数量足够大, 目前的技术还用不完.
IPv4 还在向 IPv6 过渡... 

IPv4的5类地址, 私有地址及其他地址: 

cl IP-Begin IP-End 默认子网演码 子网数量 单网容量 总容量 备注
A 0.0.0.0 127.255.255.255 255.0.0.0 126 16387064 2064770064 互联网使用
B 128.0.0.0 191.255.255.255 255.255.0.0 14994 64516 967352904
C 192.0.0.0 223.255.255.255 255.255.255.0 7874 254 1999996
D 224.0.0.0 239.255.255.255   15     组播
E 240.0.0.0 255.255.255.255   15     实验
cl 私有-起 私有-止 默认子网演码 子网数量 单网容量 总容量 备注
A 10.0.0.0 10.255.255.255 255.0.0.0 1 16387064 16387064 跨国公司
B 172.16.0.0 172.31.255.255 255.255.0.0 16 64516 1032256 大型公司
C 192.168.0.0 192.168.255.255 255.255.255.0 1 254 254 小公司,家庭
cl IP-Begin IP-End 默认子网演码 子网数量 单网容量 总容量 备注
A 100.64.0.0 100.127.255.255 运营商级NAT 63 64516 4064508  
B 169.254.0.0 169.254.255.255 链路本地网络地址       DHCP异常
C 192.0.2.0 192.0.2.255 测试网络地址        

特殊地址还有:0; 127; 255

  • 0:网络地址 IPv4[0.0.0.0]; IPv6[::/0]
  • 127:回环地址 IPv4[127.0.0.1]; IPv6[::1]
  • 255:广播地址 IPv4[~255]; IPv6不使用广播, 使用组播.

2. iptables

Netfilter 防火墙; iptables 防火墙管理程序. Linux3.13, 新的过滤机制被加入: nftables.
Netfilter(iptables)使用了3个内置的过滤器链: input, output, forward.
Netfilter防火墙有3个独立的表: (filter:默认基础表, nat:NAT转换, mangle:对数据包特殊处理); 其他表: (raw, security).
https://wiki.archlinux.org/title/Iptables
https://www.netfilter.org/projects/iptables/index.html
https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html
https://en.wikipedia.org/wiki/Iptables
2种处理不需要的包的方式
  • REJECT 驳回 Rejecting 数据包被丢弃, 返回ICMP错误消息; 
  • DROP 丢弃 Denying 静静的丢掉数据包... 

2.1 iptables 语法

iptables <option> <chain> <matching criteria> <target>

  • option 选项, 1个或多个: -A 追加
  • chain 规则链, : input, output, forward, 其他自定义...
  • match 匹配标准集, 应用条件: 端口等...
  • target 目标或处置disposition: drop 丢弃; accept 接受

2.2 filter表对规则链的操作

  • -N <chain>  创建一个用户自定义的规则链
  • -F <chain>  清空此规则链中的规则, 如果没有指定规则链, 则清空所有规则链中的规则
  • -X <chain>  删除用户自定义规则链, 如果没有指定规则链, 则删除所有用户自定义规则链
  • -P <chain> <policy>  为内建规则链(INPUT, OUTPUT, FORWARD)设置默认策略: ACCETP or DROP
  • -L <chain>  列出此规则链中的规则, 如果没有指定规则链, 则列出所有规则链中的规则
  • -Lnv <chain>  同上, n显示IP及端口号而不是名称, v显示数据包和字节数.
  • -L --line-numbers 显示规则在规则链中的行号
  • -S <chain>  以iptables save格式显示
  • -Z <chain>  重置与每个规则链相关的数据包和字节计数器. 
  • -h | <some command> -h  列出相关命令和选项
  • -E <old chain>  重命名用户自定义规则链

2.3 filter表对规则的操作

  • -A <chain> <rule specification>  将一条规则添加到规则链的末尾
  • -I <chain> [<rule number>]  将一条规则插入到规则行号前. 若不指定行号, 则插入为第一条规则
  • -R <chain> <rule number>  替换规则链中的该行号的规则
  • -D <chain> <rule number>  删除规则链中的该行号的规则
  • -C <chain> <rule specification>  检查规则链中是否有某条规则匹配<rule specification>

2.4 filter表的基本匹配操作

  • -i <interface>  在INPUT, FORWARD或用户自定义规则链中, 对传入数据包指定规则将应用到的接口名. 如果没有指定接口名, 规则默认应用与所有接口.
  • -o <interface>  在OUTPUT, FORWARD或用户自定义规则链中, 对传出数据包指定规则将应用到的接口名. 如果没有指定接口名, 规则默认应用与所有接口.
  • -p [<protocol>]  制定规则应用到的IP协议, 内建协议有TCP, UDP, ICMP等. 协议值可以是名称或数值: $ cat /etc/protocols
  • -s [!] <address>[</mask>]  指定IP报头中的主机或网络源地址
  • -d [!] <address>[</mask>]  指定IP报头中的主机或网络目的地址
  • -j <target>  jump 如果数据包匹配规则, 则设置此数据包的处置策略, 默认目标包括内建的策略, 扩展策略, 或用户自定义规则链
  • -g <chain>  goto 指明此过程应该在指定的规则链中继续, 但不必发挥处理.(类似-j选项)
  • -m <match>  使用扩展来测试是否匹配
  • [!] -f  指定数据包的第二个和其余的分片. 否定的版本指定了非分片的数据包.
  • -c <packets> <bytes>  初始化数据包和字节计数器

规则目标是可选的: 如果数据包匹配了没有目标处置的某条规则, 则数据包计数器会被更新, 但规则链的遍历则会继续进行.

3. 其他filter表匹配操作

3.1 tcp filter表匹配操作

$ iptables -p tcp -h
tcp match options:
[!] --tcp-flags mask compmatch when TCP flags & mask == comp 对屏蔽列表位进行测试, 其中下列位必须设置为1, 才能够实现匹配
(Flags: SYN ACK FIN RST URG PSH ALL NONE)
[!] --synmatch when only SYN flag set  在初始连接请求中, 必须设置SYN标志.
(equivalent to --tcp-flags SYN,RST,ACK,FIN SYN)
[!] --source-port port[:port]   指明源端口
 --sport ...match source port(s)
[!] --destination-port port[:port]  指明目的端口
 --dport ...match destination port(s)
[!] --tcp-option number        match if TCP option set  tcp唯一的合法选项是发送方能接受的数据包的最大值

3.2 udp filter表匹配操作

$ iptables -p udp -h
udp match options:
[!] --source-port port[:port]
 --sport ...match source port(s)
[!] --destination-port port[:port]
 --dport ...match destination port(s)

3.3 icmp filter表匹配操作

$ iptables -p icmp -h
icmp match options:
[!] --icmp-type typenamematch icmp type  指定ICMP名称, ICMP类型被用于代替源端口号
[!] --icmp-type type[/code](or numeric type or type/code) 或类型号.
Valid ICMP Types:
...

4. filter 表目标扩展

iptables -j <TARGET> -h

  • $ iptables -j LOG -h  日志记录
  • $ iptables -j REJECT -h  驳回
  • $ iptables -j ULOG -h  扩展日志记录

5. filter 表匹配扩展

$ iptables -m icmp -h
$ iptables -m tcp -h
$ iptables -m udp -h

5.1 multiport

$ iptables -m multiport -h
multiport match options:
[!] --source-ports port[,port:port,port...]
 --sports ...match source port(s)  指定源端口
[!] --destination-ports port[,port:port,port...]
 --dports ...match destination port(s)  指定目的端口
[!] --ports port[,port:port,port]match both source and destination port(s)  源端口和目的端口相同, 并和列表中的端口匹配

5.2 limit

$ iptables -m limit -h
limit match options:
--limit avgmax average match rate: default 3/hour  在指定时间内匹配数据包的最大值
                                [Packets per second unless followed by /sec /minute /hour /day postfixes]
--limit-burst numbernumber to match in a burst, default 5  在应用限制前匹配的初始数据包的最大值

5.3 state

$ iptables -m state -h
state match options:
 [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]State(s) to match 如果连接状态在列表中, 则进行匹配

5.4 mac

$ iptables -m mac -h
mac match options:
[!] --mac-source XX:XX:XX:XX:XX:XXMatch source MAC address  匹配二层MAC地址, 在传入以太帧中以xx...xx(6组8进制)形式指定

5.5 owner

$ iptables -m owner -h
owner match options:
[!] --uid-owner userid[-userid]      Match local UID
[!] --gid-owner groupid[-groupid]    Match local GID
[!] --socket-exists                  Match if socket exists
    --suppl-groups                   Also match supplementary groups set with --gid-owner

5.6 mark

$ iptables -m mark -h
mark match options:
[!] --mark value[/mask]    Match nfmark value with optional mask

5.7 tos

$ iptables -m tos -h
tos match options:
[!] --tos value[/mask]    Match Type of Service/Priority field value
[!] --tos symbol          Match TOS field (IPv4 only) by symbol
                          Accepted symbolic names for value are:
                          (0x10) 16 Minimize-Delay
                          (0x08)  8 Maximize-Throughput
                          (0x04)  4 Maximize-Reliability
                          (0x02)  2 Minimize-Cost
                          (0x00)  0 Normal-Service

5.8 addrtype

$ iptables -m addrtype -h
Address type match options:
 [!] --src-type type[,...]      Match source address type
 [!] --dst-type type[,...]      Match destination address type
     --limit-iface-in           Match only on the packet's incoming device
     --limit-iface-out          Match only on the packet's outgoing device
Valid types:           
                                UNSPEC
                                UNICAST
                                LOCAL本地地址
                                BROADCAST广播地址
                                ANYCAST任意数据包
                                MULTICAST组播地址
                                BLACKHOLE黑洞地址
                                UNREACHABLE不可达地址
                                PROHIBIT禁止地址
                                THROW
                                NAT
                                XRESOLVE

5.9 iprange

$ iptables -m iprange -h
iprange match options:
[!] --src-range ip[-ip]    Match source IP in the specified range
[!] --dst-range ip[-ip]    Match destination IP in the specified range

5.a length

$ iptables -m length -h
length match options:
[!] --length length[:length]    Match packet length against value or range of values (inclusive)

5.b conntrack

$ iptables -m conntrack -h
conntrack match options:
[!] --ctstate {INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|SNAT|DNAT}[,...]State(s) to match 匹配状态
[!] --ctproto proto            Protocol to match; by number or name, e.g. "tcp"
[!] --ctorigsrc address[/mask]
[!] --ctorigdst address[/mask]
[!] --ctreplsrc address[/mask]
[!] --ctrepldst address[/mask]Original/Reply source/destination address
[!] --ctorigsrcport port
[!] --ctorigdstport port
[!] --ctreplsrcport port
[!] --ctrepldstport portTCP/UDP/SCTP orig./reply source/destination port
[!] --ctstatus {NONE|EXPECTED|SEEN_REPLY|ASSURED|CONFIRMED}[,...]Status(es) to match
[!] --ctexpire time[:time]     Match remaining lifetime in seconds againstvalue or range of values (inclusive)
    --ctdir {ORIGINAL|REPLY}   Flow direction of packet

6. 简单防火墙

$ ll /etc/iptables/
lrwxrwxrwx  1 root root   36 2021-01-21 05:31 empty.rules -> ../../usr/share/iptables/empty.rules
-rw-r--r--  1 root root  105 2021-01-21 05:31 ip6tables.rules
-rw-r--r--  1 root root  728 2021-05-20 22:59 iptables.rules
lrwxrwxrwx  1 root root   46 2021-01-21 05:31 simple_firewall.rules -> ../../usr/share/iptables/simple_firewall.rules
$ cat /usr/share/iptables/simple_firewall.rules 
这里的simple_firewall.rules就是系统自带的可用于普通用户电脑的简单防火墙. 
最简单的使用方式就是用这个文件覆盖iptables.rules, 然后重新运行iptable服务即可. 

下面是摘录自arch页面用于单台计算机的防火墙的内容, 或许比上面那个最简单的稍微好一点点. 更重要的是, 每个步骤都有说明.
https://wiki.archlinux.org/title/Simple_stateful_firewall

6.1 准备

本文假定当前没有设置iptables规则. 要检查当前规则集并验证当前没有规则, 请运行以下命令:
$ sudo iptables-save
or
$ sudo iptables -nvL --line-numbers
如果有规则, 则可以通过加载默认规则集来重置规则:
$ sudo iptables-restore < /etc/iptables/empty.rules

6.2 一台机器的防火墙

注意: 由于iptables以线性顺序处理规则(从上到下), 因此建议将频繁访问的规则放在链的开头附近. 
当然, 有一个限制, 具体取决于要实现的逻辑. 而且, 规则具有相关的运行时成本, 因此不应仅基于对字节/数据包计数器的经验观察来对规则进行重新排序. 
创建必要的链: 对于此基本设置, 我们将创建两个用户定义的链, 这些链将用于打开防火墙中的端口. 
$ sudo iptables -N TCP
$ sudo iptables -N UDP

转发链: 
$ sudo iptables -P FORWARD DROP

输出链: 在这个简单的示例中, 我们将OUTPUT链的默认策略设置为ACCEPT, 以允许所有出站流量. 这不太安全, 但是与许多系统高度兼容. 
$ sudo iptables -P OUTPUT ACCEPT

输入链: 与以前的链类似, 我们将INPUT链的默认策略设置为DROP, 以防某些情况导致我们的规则滑脱. 丢弃所有流量并指定允许的内容是制造安全防火墙的最佳方法. 这里暂不考虑ssh等服务.
$ sudo iptables -P INPUT DROP

如果任何网络接口接收到的每个数据包都发往本机, 则它将首先通过INPUT链. 在此链中, 我们确保仅接受所需的数据包.
添加到INPUT链的第一个规则将允许属于已建立连接的流量, 或与这些连接相关的新有效流量.
例如ICMP错误或回显答复(主机被ping后返回的数据包). ICMP代表Internet控制消息协议. 一些ICMP消息非常重要, 有助于管理拥塞和MTU, 并且被以下规则接受: 
$ sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

连接状态ESTABLISHED表示, 另一个规则先前允许进行初始(--ctstate NEW)连接尝试, 或者该连接已经处于活动状态(例如, 活动的远程SSH连接).
第二条规则将接受来自“环回”(lo)接口的所有流量, 这对于许多应用程序和服务都是必需的. 
$ sudo iptables -A INPUT -i lo -j ACCEPT

第三条规则将丢弃状态匹配为“INVALID”的所有流量.
流量可以分为四个“状态”state: (NEW 新的, ESTABLISHED 已建立的, RELATED 相关的 或 INVALID无效的), 这就是使它成为“有状态”防火墙而不是不太安全的“无状态”防火墙的原因.
使用“nf_conntrack_ *”内核模块跟踪状态, 这些模块在添加规则时由内核自动加载.
$ sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

下一条规则将接受所有新的传入ICMP回显请求, 也称为ping. 只有第一个数据包将被视为新数据包, 其他数据包将由RELATED, ESTABLISHED规则处理. 由于计算机不是路由器, 因此不需要允许其他状态为NEW的ICMP通信.
$ sudo iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

现在, 我们将TCP和UDP链附加到INPUT链, 以处理所有新的传入连接. 一旦连接被TCP或UDP链接受, 则由RELATED/ESTABLISHED通信规则处理. TCP和UDP链将接受新的传入连接, 或者有礼貌地拒绝它们. 新的TCP连接必须以SYN数据包开始.
注意: NEW(不是SYN)是INVALID状态未涵盖的唯一无效TCP标志. 这是因为它们很少是恶意数据包, 不应仅被丢弃. 取而代之的是, 它们将由下一条规则简单地通过TCP RESET拒绝.
$ sudo iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
$ sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP

如果未打开端口, 我们将拒绝带有TCP RESET数据包的TCP连接和带有ICMP端口不可达消息的UDP流. 这模仿了默认的Linux行为(符合RFC), 并允许发送方快速关闭连接并进行清理.
$ sudo iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
$ sudo iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

对于其他协议, 我们向INPUT链添加最终规则, 以拒绝icmp协议不可达消息的所有剩余传入流量. 这模仿了Linux的默认行为.
$ sudo iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

生成的iptables.rules文件, 首先查看: 
$ sudo iptables -nvL --line-numbers
$ sudo iptables -S

该文件可以通过以下方式生成和保存: 
$ sudo iptables-save -f /etc/iptables/iptables.rules

6.3 临时许可某端口

若在局域网内有与其他局域网分享文件的需要, 可以使用时手动添加相应的端口, 这些临时开放的规则不必保存到文件.
要在Web服务器的端口8000上接受传入的TCP连接, 请执行以下操作:
$ sudo iptables -A TCP -p tcp --dport 8000 -j ACCEPT

若不再需要了可进行删除操作: 若不删除, 这个没有保存到配置文件的, 重启后也不会存在.
$ sudo iptables -nvL --line-numbers
$ sudo iptables -D <rule number>

最后别忘了重启服务
$ sudo systemctl status iptables.service
$ sudo systemctl restart iptables.service
$ sudo systemctl enable iptables.service