##
連線追蹤(conntrack)
連線追蹤是許多網路應用程式的基礎。例如,Kubernetes Service、ServiceMesh sidecar、 軟體四層負載平衡器 LVS/IPVS、Docker network、OVS、iptables 主機防火牆等等,都依賴連線追蹤功能。 連線跟踪,顧名思義,就是追蹤(並記錄)連線的狀態。 例如,圖1.1 是一台IP 位址為10.1.1.2 的Linux 機器,我們可以看到這台機器上有三個連接:
- 機器存取外部HTTP 服務的連線(目的連接埠80)
- #外部存取機器內FTP 服務的連線(目的連接埠21)
- #機器存取外部DNS 服務的連接(目的連接埠53)
連接追蹤所做的事情就是發現並追蹤這些連接的狀態,具體包括:
- 從資料包中提取元組(tuple)信息,辨別資料流(flow)和對應的連接( connection)。
- 為所有連線維護一個狀態資料庫(conntrack table),例如連線的建立時間、傳送 包數、傳送位元組數等等。
需要注意的是,連接追蹤中所說的“連接”,概念和TCP/IP 協定中“面向連接”(connection oriented)的“連接」並不完全相同,簡單來說:
- TCP/IP 協定中,連接是一個四層(Layer 4)的概念。 TCP 是有連線的,或稱為連線導向的(connection oriented),傳送出去的套件都要求對端應答(ACK),並且有重傳機制。 UDP 是無連接的,發送的包無需對端應答,也沒有重傳機制。
- conntrack(CT) 中,一個元組(tuple)定義的一條資料流(flow )就表示一條連接(connection)。後面會看到 UDP 甚至是 ICMP 這種三層協定在 CT 中也都是有連線記錄的,但不是所有協定都會被連線追蹤。
Netfilter
Linux的連線追蹤是在Netfilter 中實現的。 Netfilter 是 Linux 核心中一個對資料 套件進行控制、修改和過濾(manipulation and filtering)的框架。它在核心協定堆疊中設定了若干 hook 點,以此對資料包進行攔截、過濾或其他處理。現在提到連線追蹤(conntrack),可能會先想到 Netfilter,Netfilter 只是 Linux 核心中的一種連線追蹤實作。換句話說,只要具備了 hook 能力,能攔截到進出主機的每個包,完全可以在此基礎上自己實現一套連接追蹤。 雲端原生網路方案Cilium 在1.7.4 版本就實現了這樣一套獨立的連線追蹤和NAT 機制(完備功能需要Kernel 4.19 )。其基本原理是:
- 基於BPF hook 實作封包的攔截功能(等價於netfilter 裡面的hook 機制)
- #在BPF hook 的基礎上,實現一套全新的conntrack 和NAT 因此,即使卸載掉Netfilter ,也不會影響Cilium 對Kubernetes ClusterIP、NodePort、ExternalIPs 和LoadBalancer 等功能的支持。由於這套連接追蹤機制是獨立於 Netfilter 的,因此它的 conntrack 和 NAT 資訊也沒有 儲存在內核的(也就是 Netfilter 的)conntrack table 和 NAT table。所以常規的conntrack/netstats/ss/lsof 等工具是看不到的,要使用Cilium 的指令,例如:
$ cilium bpf nat list$ cilium bpf ct list global
Iptables
Iptables 是設定Netfilter 過濾功能的使用者空間工具。 netfilter 才是防火牆真正的安全框架(framework),netfilter 位於核心空間。 iptables 其實是命令列工具,位於使用者空間,我們用這個工具操作真正的框架。 Iptable 根據規則所定義的方法來處理封包,如放行(accept)、拒絕(reject)和丟棄(drop)等。 例如當客戶端存取伺服器的web服務時,客戶端發送封包到網卡,而tcp/ip 協定堆疊是屬於核心的一部分,所以,客戶端的資訊會通過核心的TCP 協定傳輸到用戶空間中的web 服務中,而此時,客戶端封包的目標終點為web 服務所監聽的套接字(IP:Port)上,當web服務需要回應客戶端請求時,web 服務發出的回應封包的目標終點則為客戶端,這個時候,web 服務所監聽的IP 與連接埠反而變成了原點,我們說過,netfilter 才是真正的防火牆,它是核心的一部分,所以,如果我們想要防火牆能夠達到」防火」的目的,則需要在內核中設定關卡,所有進出的報文都要通過這些關卡,經過檢查後,符合放行條件的才能放行,符合阻攔條件的則需要被阻止。 iptables 包含 4個表,5個鏈。其中表是依照對資料包的操作區分(過濾, NAT等)的,鍊是依照不同的 Hook 點來區分的,表和鏈其實是netfilter的兩個維度。iptables 的四個表格分別是 filter,mangle,nat,raw,預設表格是filter。
- filter 表:用來對封包進行過濾,具體的規則要求決定如何處理一個封包。
- nat 表:主要用來修改封包的 IP 位址、連接埠號碼資訊。
- mangle 表:主要用來修改封包的服務類型,生存週期,為封包設定標記,實現流量整形、策略路由等。
iptables 的五個鏈分別是 PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING。
- input 鏈:當收到存取本機位址的封包時,將會套用此鏈中的規則。
- output 鏈:當本機向外傳送資料包時,將會套用此鏈中的規則。
- forward 鏈:當收到需要轉送給其他位址的封包時,將會套用此鏈中的規則,注意如果需要實作forward轉送需要開啟Linux核心中的ip_forward功能。
- prerouting 鏈:在對封包做路由選擇之前,將套用此鏈中的規則。
- postrouting 鏈:在對封包做路由選擇之後,將套用此鏈中的規則。
- 到本機某進程的封包:PREROUTING –> INPUT。
- 由本機轉送的封包:PREROUTING –> FORWARD –> POSTROUTING。
- 由本機的某進程發出封包(通常為回應封包):OUTPUT –> POSTROUTING。
查詢規則
- --line-numbers:顯示規則的序號(簡寫為--line)
- 另外,搜尋公眾號Linux就該這樣學後台回覆“猴子”,獲取一份驚喜禮包。
#iptables -t filter -nvxL DOCKER --lineChain DOCKER (1 references)num pkts bytes target prot opt in out source destination1 5076 321478 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 tcp dpt:84432 37233 54082508 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 tcp dpt:223 1712 255195 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.3 tcp dpt:90004 0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.3 tcp dpt:80005 40224 6343104 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.4 tcp dpt:34436 21034 2227009 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.5 tcp dpt:33067 58 5459 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.6 tcp dpt:808 826 70081 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.6 tcp dpt:4439 10306905 1063612492 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.9 tcp dpt:330610 159775 12297727 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.7 tcp dpt:11111
增加规则
在指定表的指定链的尾部添加一条规则,-A 选项表示在对应链的末尾添加规则,省略 -t 选项时,表示默认操作 filter 表中的规则:命令语法:iptables -t 表名 -A 链名 匹配条件 -j 动作示例:iptables -t filter -A INPUT -s 192.168.1.146 -j DROP
在指定表的指定链的首部添加一条规则,-I 选型表示在对应链的开头添加规则:命令语法:iptables -t 表名 -I 链名 匹配条件 -j 动作示例:iptables -t filter -I INPUT -s 192.168.1.146 -j ACCEPT
命令语法:iptables -t 表名 -I 链名 规则序号 匹配条件 -j 动作示例:iptables -t filter -I INPUT 5 -s 192.168.1.146 -j REJECT
删除规则
按照规则序号删除规则,删除指定表的指定链的指定规则,-D 选项表示删除对应链中的规则。示例表示删除filter表中INPUT链中序号为3的规则。:命令语法:iptables -t 表名 -D 链名 规则序号示例:iptables -t filter -D INPUT 3
按照具体的匹配条件与动作删除规则,删除指定表的指定链的指定规则。示例表示删除filter表中INPUT链中源地址为192.168.1.146并且动作为DROP的规则。:命令语法:iptables -t 表名 -D 链名 匹配条件 -j 动作示例:iptables -t filter -D INPUT -s 192.168.1.146 -j DROP
删除指定表的指定链中的所有规则,-F选项表示清空对应链中的规则:命令语法:iptables -t 表名 -F 链名示例:iptables -t filter -F INPUT
修改规则
修改指定表中指定链的指定规则,-R 选项表示修改对应链中的规则,使用 -R 选项时要同时指定对应的链以及规则对应的序号,并且规则中原本的匹配条件不可省略。示例表示修改filter表中INPUT链的第3条规则,将这条规则的动作修改为ACCEPT, -s 192.168.1.146为这条规则中原本的匹配条件,如果省略此匹配条件,修改后的规则中的源地址可能会变为0.0.0.0/0:命令语法:iptables -t 表名 -R 链名 规则序号 规则原本的匹配条件 -j 动作示例:iptables -t filter -R INPUT 3 -s 192.168.1.146 -j ACCEPT
命令语法:iptables -t 表名 -P 链名 动作示例:iptables -t filter -P FORWARD ACCEPT
保存规则
方式一
当我们对规则进行了修改以后,如果想要修改永久生效,必须使用下面命令保存规则:service iptables save
当然,如果你误操作了规则,但是并没有保存,那么使用 service iptables restart 命令重启 iptables 以后,规则会再次回到上次保存 /etc/sysconfig/iptables 文件时的模样。centos7 中,已经不再使用 init 风格的脚本启动服务,而是使用 unit 文件,所以,在 centos7 中已经不能再使用类似 service iptables start 这样的命令了,所以 service iptables save 也无法执行,同时,在 centos7中,使用 firewall 替代了原来的 iptables service,不过不用担心,我们只要通过 yum 源安装 iptables与iptables-services 即可(iptables 一般会被默认安装,但是iptables-services 在 centos7 中一般不会被默认安装),在centos7 中安装完 iptables-services 后,即可像 centos6 中一样,通过 service iptables save 命令保存规则了,规则同样保存在 /etc/sysconfig/iptables 文件中。此处给出 centos7 中配置 iptables-service 的步骤:#配置好yum源以后安装iptables-serviceyum install -y iptables-services#停止firewalldsystemctl stop firewalld#禁止firewalld自动启动systemctl disable firewalld#启动iptablessystemctl start iptables#将iptables设置为开机自动启动,以后即可通过iptables-service控制iptables服务systemctl enable iptables
上述配置过程只需一次,以后即可在 centos7 中使用 service iptables save 命令保存 iptables 规则了。方式二
还可以使用另一种方法保存 iptables 规则,就是使用 iptables-save 命令。使用 iptables-save 并不能保存当前的 iptables 规则,但是可以将当前的 iptables 规则以”保存后的格式”输出到屏幕上。所以,我们可以使用 iptables-save 命令,再配合重定向,将规则重定向到 /etc/sysconfig/iptables 文件中即可。iptables-save > /etc/sysconfig/iptables
加载规则
我们也可以将 /etc/sysconfig/iptables 中的规则重新载入为当前的iptables 规则,但是注意,未保存入 /etc/sysconfig/iptables 文件中的修改将会丢失或者被覆盖。使用 iptables-restore 命令可以从指定文件中重载规则,示例如下iptables-restore < /etc/sysconfig/iptables
匹配条件
当规则中同时存在多个匹配条件时,多个条件之间默认存在”与”的关系,即报文必须同时满足所有条件,才能被规则匹配。-s 用于匹配报文的源地址,可以同时指定多个源地址,每个IP之间用逗号隔开,也可以指定为一个网段。#示例如下iptables -t filter -I INPUT -s 192.168.1.111,192.168.1.118 -j DROPiptables -t filter -I INPUT -s 192.168.1.0/24 -j ACCEPTiptables -t filter -I INPUT ! -s 192.168.1.0/24 -j ACCEPT
-d 用于匹配报文的目标地址,可以同时指定多个目标地址,每个 IP 之间用逗号隔开,也可以指定为一个网段。#示例如下iptables -t filter -I OUTPUT -d 192.168.1.111,192.168.1.118 -j DROPiptables -t filter -I INPUT -d 192.168.1.0/24 -j ACCEPTiptables -t filter -I INPUT ! -d 192.168.1.0/24 -j ACCEPT
-p 用于匹配报文的协议类型,可以匹配的协议类型 tcp、udp、udplite、icmp、esp、ah、sctp 等(centos7 中还支持 icmpv6、mh)。#示例如下iptables -t filter -I INPUT -p tcp -s 192.168.1.146 -j ACCEPTiptables -t filter -I INPUT ! -p udp -s 192.168.1.146 -j ACCEPT
-i 用于匹配报文是从哪个网卡接口流入本机的,由于匹配条件只是用于匹配报文流入的网卡,所以在 OUTPUT 链与 POSTROUTING 链中不能使用此选项。#示例如下iptables -t filter -I INPUT -p icmp -i eth4 -j DROPiptables -t filter -I INPUT -p icmp ! -i eth4 -j DROP
-o 用于匹配报文将要从哪个网卡接口流出本机,于匹配条件只是用于匹配报文流出的网卡,所以在 INPUT 链与 PREROUTING 链中不能使用此选项。#示例如下iptables -t filter -I OUTPUT -p icmp -o eth4 -j DROPiptables -t filter -I OUTPUT -p icmp ! -o eth4 -j DROP
扩展匹配条件
tcp扩展模块
- –sport:用于匹配 tcp 协议报文的源端口,可以使用冒号指定一个连续的端口范围。
- –dport:用于匹配 tcp 协议报文的目标端口,可以使用冒号指定一个连续的端口范围。
- –tcp-flags:用于匹配报文的tcp头的标志位。
- –syn:用于匹配 tcp 新建连接的请求报文,相当于使用
<span style="outline: 0px;font-size: 17px;">–tcp-flags SYN,RST,ACK,FIN SYN</span>
。
注意,-p tcp与 -m tcp 并不冲突,-p 用于匹配报文的协议,-m 用于指定扩展模块的名称,正好,这个扩展模块也叫 tcp。#示例如下iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECTiptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22:25 -j REJECTiptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport :22 -j REJECTiptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 80: -j REJECTiptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPTiptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECTiptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK -j REJECTiptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECTiptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags ALL SYN,ACK -j REJECTiptables -t filter -I INPUT -p tcp -m tcp --dport 22 --syn -j REJECT
udp 扩展模块
#示例iptables -t filter -I INPUT -p udp -m udp --dport 137 -j ACCEPTiptables -t filter -I INPUT -p udp -m udp --dport 137:157 -j ACCEPT
icmp 扩展模块
- –icmp-type:匹配icmp报文的具体类型。
#示例iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECTiptables -t filter -I INPUT -p icmp --icmp-type 8 -j REJECTiptables -t filter -I OUTPUT -p icmp -m icmp --icmp-type 0/0 -j REJECTiptables -t filter -I OUTPUT -p icmp --icmp-type 0 -j REJECTiptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT
multiport 扩展模块
- -p tcp -m multiport –sports 用于匹配报文的源端口,可以指定离散的多个端口号,端口之间用”逗号”隔开。
- -p udp -m multiport –dports 用于匹配报文的目标端口,可以指定离散的多个端口号,端口之间用”逗号”隔开。
#示例如下iptables -t filter -I OUTPUT -d 192.168.1.146 -p udp -m multiport --sports 137,138 -j REJECTiptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80 -j REJECTiptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport ! --dports 22,80 -j REJECTiptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 80:88 -j REJECTiptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80:88 -j REJECT
iprange 模块
#示例iptables -t filter -I INPUT -m iprange --src-range 192.168.1.127-192.168.1.146 -j DROPiptables -t filter -I OUTPUT -m iprange --dst-range 192.168.1.127-192.168.1.146 -j DROPiptables -t filter -I INPUT -m iprange ! --src-range 192.168.1.127-192.168.1.146 -j DROP
牛逼啊!接私活必备的 N 个开源项目!赶快收藏
string 模块
- –algo:指定对应的匹配算法,可用算法为bm、kmp,此选项为必需选项。
我们想要达到的目的是,如果报文中包含”OOXX”字符,我们就拒绝报文进入本机:#示例
iptables -t filter -I INPUT -m string --algo bm --string "OOXX" -j REJECT
time 模块
- –timestart:用于指定时间范围的开始时间,不可取反。
- –timestop:用于指定时间范围的结束时间,不可取反。
- –datestart:用于指定日期范围的开始日期,不可取反。
- –datestop:用于指定日期范围的结束时间,不可取反。
#示例
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 443 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time ! --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --datestart 2017-12-24 --datestop 2017-12-27 -j REJECT
connlimit 模块
- –connlimit-above:单独使用此选项时,表示限制每个IP的链接数量。
- –connlimit-mask:此选项不能单独使用,在使用–connlimit-above选项时,配合此选项,则可以针对”某类IP段内的一定数量的IP”进行连接数量的限制,如果不明白可以参考上文的详细解释。
#示例
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j REJECT
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 --connlimit-mask 27 -j REJECT
limit 模块
connlimit 模块是对连接数量进行限制的,limit 模块是对”报文到达速率”进行限制的。用大白话说就是,如果我想要限制单位时间内流入的包的数量,就能用 limit 模块。我们可以以秒为单位进行限制,也可以以分钟、小时、天作为单位进行限制。常用的扩展匹配条件如下:
- –limit-burst:类比”令牌桶”算法,此选项用于指定令牌桶中令牌的最大数量。
- –limit:类比”令牌桶”算法,此选项用于指定令牌桶中生成新令牌的频率,可用时间单位有second、minute 、hour、day。
示例表示限制外部主机对本机进行ping操作时,本机最多每6秒中放行一个ping包#示例,注意,如下两条规则需配合使用
#令牌桶中最多能存放3个令牌,每分钟生成10个令牌(即6秒钟生成一个令牌)。
iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT
#默认将icmp包丢弃
iptables -t filter -A INPUT -p icmp -j REJECT
state 扩展模块
当我们通过 http 的 url 访问某个网站的网页时,客户端向服务端的 80 端口发起请求,服务端再通过 80 端口响应我们的请求,于是,作为客户端,我们似乎应该理所应当的放行 80 端口,以便服务端回应我们的报文可以进入客户端主机,于是,我们在客户端放行了 80 端口,同理,当我们通过 ssh 工具远程连接到某台服务器时,客户端向服务端的 22 号端口发起请求,服务端再通过 22 号端口响应我们的请求,于是我们理所应当的放行了所有 22 号端口,以便远程主机的响应请求能够通过防火墙,但是,作为客户端,如果我们并没有主动向 80 端口发起请求,也没有主动向 22 号端口发起请求,那么其他主机通过 80 端口或者 22 号端口向我们发送数据时,我们可以接收到吗?应该是可以的,因为我们为了收到 http 与 ssh 的响应报文,已经放行了 80 端口与 22 号端口,所以,不管是”响应”我们的报文,还是”主动发送”给我们的报文,应该都是可以通过这两个端口的,那么仔细想想,这样是不是不太安全呢?此时 state 扩展模块就派上用场了。對於state 模組的連接而言,」連接」其中的封包可以分為5種狀態,分別為:
- #NEW:連線中的第一個包,狀態就是NEW,我們可以理解為新連線的第一個包的狀態為NEW。
- ESTABLISHED:我們可以把 NEW 狀態包後面的套件的狀態理解為 ESTABLISHED,表示連接已建立。
- RELATED:字面上理解 RELATED 譯為關係,但是這樣仍然不容易理解,我們舉個例子。例如 FTP 服務,FTP 服務端會建立兩個進程,一個命令進程,一個資料進程。命令進程負責服務端與客戶端之間的命令傳輸(我們可以把這個傳輸過程理解成 state 中所謂的一個”連接”,暫稱為”命令連接”)。資料進程負責服務端與客戶端之間的資料傳輸 (我們把這個過程暫稱為」資料連線」)。但是具體傳輸哪些數據,是由命令去控制的,所以,”數據連接”中的報文與”命令連接”是有”關係」的。那麼,」資料連線」中的封包可能就是 RELATED 狀態,因為這些封包與」指令連線」中的封包有關係。 (註:如果想要對ftp進行連接追踪,需要單獨加載對應的核心模組nf_conntrack_ftp,如果想要自動加載,可以配置/etc/sysconfig/iptables-config 檔案)
- #INVALID:如果一個套件沒有辦法被識別,或是這個套件沒有任何狀態,那麼這個套件的狀態就是INVALID,我們可以主動封鎖狀態為INVALID 的訊息。
- UNTRACKED:封包的狀態為untracked 時,表示封包未被追踪,當封包的狀態為Untracked 時通常表示無法找到相關的連接。
刚才举例中的问题即可使用 state 扩展模块解决,我们只要放行状态为 ESTABLISHED 的报文即可,因为如果报文的状态为 ESTABLISHED,那么报文肯定是之前发出的报文的回应,这样,就表示只有回应我们的报文能够通过防火墙,如果是别人主动发送过来的新的报文,则无法通过防火墙:iptables -t filter -I INPUT -m state --state ESTABLISHED -j ACCEPT
mangle 表
mangle 表的主要功能是根据规则修改数据包的一些标志位,以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。mangle 表主要有以下 3 种操作:
- TOS:用来设置或改变数据包的服务类型域。这常用来设置网络上的数据包如何被路由等策略。注意这个操作并不完善,有时得不所愿。它在Internet 上还不能使用,而且很多路由器不会注意到这个域值。换句话说,不要设置发往 Internet 的包,除非你打算依靠 TOS 来路由,比如用 iproute2。
- TTL:用来改变数据包的生存时间域,我们可以让所有数据包只有一个特殊的 TTL。它的存在有 一个很好的理由,那就是我们可以欺骗一些ISP。为什么要欺骗他们呢?因为他们不愿意让我们共享一个连接。那些 ISP 会查找一台单独的计算机是否使用不同的 TTL,并且以此作为判断连接是否被共享的标志。
- MARK 用来给包设置特殊的标记。iproute 2能识别这些标记,并根据不同的标记(或没有标记) 决定不同的路由。用这些标记我们可以做带宽限制和基于请求的分类。
例如内网的客户端通过 Linux 主机连入 Internet,而 Linux 主机与Internet 连接时有两条线路,它们的网关如图所示。现要求对内网进行策略路由,所有通过 TCP 协议访问 80 端口的数据包都从 ChinaNet 线路出去,而所有访问 UDP 协议 53 号端口的数据包都从 Cernet 线路出去。这是一个策略路由的问题,为了达到目的,在对数据包进行路由前,要先根据数据包的协议和目的端口给数据包做上一种标志,然后再指定相应规则,根据数据包的标志进行策略路由。为了给特定的数据包做上标志,需要使用mangle 表,mangle 表共有 5 条链,由于需要在路由选择前做标志,因此应该使用 PREROUTING 链,下面是具体的命令:iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 80 -j MARK --set-mark 1;
iptables -t mangle -A PREROUTING -i eth0 -p udp --dprot 53 -j MARK --set-mark 2;
数据包经过 PREROUTING 链后,将要进入路由选择模块,为了对其进行策略路由,执行以下两条命令,添加相应的规则:ip rule add from all fwmark 1 table 10
ip rule add from all fwmark 2 table 20
以上两条命令表示所有标志是1的数据包使用路由表 10 进行路由,而所有标志是 2 的数据包使用路由表 20 进行路由。路由表 10 和 20 分别使用了 ChinaNet 和 Cernet 线路上的网关作为默认网关,具体设置命令如下所示:ip route add default via 10.10.1.1 dev eth1 table 10
ip route add default via 10.10.2.1 dev eth2 table 20
以上两条命令在路由表 10 和 20 上分别指定了 10.10.1.1 和 10.10.2.1 作为默认网关,它们分别位于 ChinaNet 和 Cernet 线路上。于是,使用路由表 10 的数据包将通过 ChinaNet 线路出去,而使用路由表20的数据包将通过 Cernet 线路出去。自訂鏈
當預設鏈中的規則非常多時,不方便我們管理。想像一下,如果INPUT 鏈中存放了200 條規則,這200 條規則有針對httpd 服務的,有針對sshd 服務的,有針對私網IP 的,有針對公網IP 的,假如,我們突然想要修改針對httpd 服務的相關規則,我們還要從頭看一遍這200 條規則,找出哪些規則是針對httpd 的嗎?這顯然不合理。 所以,iptables 中,可以自訂鏈,透過自訂鏈即可解決上述問題。假設,我們自訂一條鏈,鏈名叫IN_WEB,我們可以將所有針對80 連接埠的入站規則都寫入到這條自訂鏈中,當以後想要修改針對web 服務的入站規則時,就直接修改IN_WEB 鏈中的規則就好了,即使預設鏈中有再多的規則,我們也不會害怕了,因為我們知道,所有針對80 連接埠的入站規則都存放在IN_WEB鏈中。创建自定义链
#在filter表中创建IN_WEB自定义链
iptables -t filter -N IN_WEB
引用自定义链
#在INPUT链中引用刚才创建的自定义链
iptables -t filter -I INPUT -p tcp --dport 80 -j IN_WEB
重命名自定义链
#将IN_WEB自定义链重命名为WEB
iptables -E IN_WEB WEB
删除自定义链
#第一步:清除自定义链中的规则
iptables -t filter -F WEB
#第二步:删除自定义链
iptables -t filter -X WEB
LOG 动作
LOG 动作默认会将报文的相关信息记录在/var/log/message文件中,当然,我们也可以将相关信息记录在指定的文件中,以防止 iptables 的相关信息与其他日志信息相混淆,修改 /etc/rsyslog.conf 文件(或者 /etc/syslog.conf),在 rsyslog 配置文件中添加如下配置即可:kern.warning /var/log/iptables.log
完成上述配置后,重启rsyslog服务(或者syslogd):service rsyslog restart
- –log-level 选项可以指定记录日志的日志级别,可用级别有 emerg,alert,crit,error,warning,notice,info,debug。
- –log-prefix 选项可以给记录到的相关信息添加”标签”之类的信息,以便区分各种记录到的报文信息,方便在分析时进行过滤。–log-prefix 对应的值不能超过 29 个字符。
比如,我想要将主动连接22号端口的报文的相关信息都记录到日志中,并且把这类记录命名为”want-in-from-port-22″,则可以使用如下命令:iptables -I INPUT -p tcp --dport 22 -m state --state NEW -j LOG --log-prefix "want-in-from-port-22"
完成上述配置后,我在IP地址为 192.168.1.98 的客户端机上,尝试使用 ssh 工具连接上例中的主机,然后查看对应的日志文件(已经将日志文件设置为 /var/log/iptables.log):如上图所示,ssh 连接操作的报文的相关信息已经被记录到了 iptables.log 日志文件中,而且这条日志中包含”标签”:want-in-from-port-22,如果有很多日志记录,我们就能通过这个”标签”进行筛选了,这样方便我们查看日志,同时,从上述记录中还能够得知报文的源IP与目标IP,源端口与目标端口等信息,从上述日志我们能够看出,192.168.1.98 这个 IP 想要在 14点11分 连接到 192.168.1.139(当前主机的 IP)的22号端口,报文由eth4网卡进入,eth4 网卡的 MAC 地址为 00:0c:29:b7:f4:d1,客户端网卡的 MAC 地址为 f4:8e:38:82:b1:29。參考連結
- #https://www.zsythink.net/archives/category/運維相關/ iptables/
- https://my.oschina.net/mojiewhy/blog/3039897
- https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html#MARKTARGET
- # https://mp.weixin.qq.com/s/NOxY4ZC7Cay4LCWlMkVx8A