[QNX_firewall]PF防火牆 最詳細的教程(上)

鋒影

email:[email protected]

如果你認爲本系列文章對你有所幫助,請大家有錢的捧個錢場,點擊此處贊助,贊助額0.1元起步,多少隨意

 

PF防火牆

PF防火牆PF ( 全稱:Packet Filter ) --- 包過濾

UNIX LIKE系統上進行TCP/IP流量過濾和網絡地址轉換的軟件系統。PF同樣也能提供TCP/IP流量的整形和控制,並且提供帶寬控制和數據包優先集控制。

PF最早是由Daniel Hartmeier開發的,現在的開發和維護由Daniel 和openbsd小組的其他成員負責。

目錄

[顯示全部]

 

編輯本段   回目錄    

PF防火牆 - 基本配置

PF防火牆激活

要激活pf並且使它在啓動時調用配置文件,編輯/etc/rc.conf文件,修改配置pf的一行:

pf=YES

重啓操作系統讓配置生效。

也可以通過pfctl程序啓動和停止pf

# pfctl -e
# pfctl -d

注意這僅僅是啓動和關閉PF,實際它不會載入規則集,規則集要麼在系統啓動時載入,要在PF啓動後通過命令單獨載入。

配置

系統引導到在rc腳本文件運行PF時PF從/etc/pf.conf文件載入配置規則。注意當/etc/pf.conf文件是默認配置文件,在系統調用rc腳本文件時,它僅僅是作爲文本文件由pfctl裝入並解釋和插入pf的。對於一些應用來說,其他的規則集可以在系統引導後由其他文件載入。對於一些設計的非常好的unix程序,PF提供了足夠的靈活性。

pf.conf 文件有7個部分:

* 宏:              用戶定義的變量,包括IP地址,接口名稱等等
* 表:              一種用來保存IP地址列表的結構
* 選項:          控制PF如何工作的變量
* 整形:          重新處理數據包,進行正常化和碎片整理
* 排隊:          提供帶寬控制和數據包優先級控制.
* 轉換:          控制網絡地址轉換和數據包重定向.
* 過濾規則:   在數據包通過接口時允許進行選擇性的過濾和阻止

除去宏和表,其他的段在配置文件中也應該按照這個順序出現,儘管對於一些特定的應用並不是所有的段都是必須的。

空行會被忽略,以#開頭的行被認爲是註釋.

 

# pfctl -sa
# pfctl -sa

控制

 

引導之後,PF可以通過pfctl程序進行操作,以下是一些例子:

pfctl -f /etc/pf.conf 載入 pf.conf 文件
pfctl -nf /etc/pf.conf 解析文件,但不載入
pfctl -Nf /etc/pf.conf 只載入文件中的NAT規則
pfctl -Rf /etc/pf.conf 只載入文件中的過濾規則

pfctl -sn 顯示當前的NAT規則
pfctl -sr 顯示當前的過濾規則
pfctl -ss 顯示當前的狀態表
pfctl -si 顯示過濾狀態和計數
pfctl -sa 顯示任何可顯示的

完整的命令列表,請參閱pfctl的man手冊頁。

編輯本段   回目錄    

PF防火牆 - 列表和宏

列表

一個列表允許一個規則集中指定多個相似的標準。例如,多個協議端口號網絡地址等等。因此,不需要爲每一個需要阻止的IP地址編寫一個過濾規則,一條規則可以在列表中指定多個IP地址。列表的定義是將要指定的條目放在{ }大括號中。

當pfctl在載入規則集碰到列表時,它產生多個規則,每條規則對於列表中的一個條目。例如:

block out on fxp0 from { 192.168.0.1, 10.5.32.6 } to any

展開後:

block out on fxp0 from 192.168.0.1 to any
block out on fxp0 from 10.5.32.6 to any

多種列表可以在規則中使用,並不僅僅限於過濾規則:

rdr on fxp0 proto tcp from any to any port { 22 80 } -> \
192.168.0.6
block out on fxp0 proto { tcp udp } from { 192.168.0.1, \
10.5.32.6 } to any port { ssh telnet }

注意逗號在列表條目之間是可有可無的。

是用戶定義變量用來指定IP地址,端口號,接口名稱等等。宏可以降低PF規則集的複雜度並且使得維護規則集變得容易。

宏名稱必須以字母開頭,可以包括字母,數字和下劃線。宏名稱不能包括保留關鍵字如:
pass, out, 以及 queue.

ext_if = "fxp0"

block in on $ext_if from any to any

這生成了一個宏名稱爲ext_if. 當一個宏在它產生以後被引用時,它的名稱前面以$字符開頭。

宏也可以展開成列表,如:

friends = "{ 192.168.1.1, 10.0.2.5, 192.168.43.53 }"

宏能夠被重複定義,由於宏不能在引號內被擴展,因此必須使用下面得語法:

host1 = "192.168.1.1"
host2 = "192.168.1.2"
all_hosts = "{" $host1 $host2 "}"

宏 $all_hosts 現在會展開成 192.168.1.1, 192.168.1.2.

編輯本段   回目錄    

PF防火牆 - 表

PF防火牆簡介

表是用來保存一組IPv4或者IPv6地址。在表中進行查詢是非常快的,並且比列表消耗更少的內存cpu時間。由於這個原因,表是保存大量地址的最好方法,在50,000個地址中查詢僅比在50個地址中查詢稍微多一點時間。表可以用於下列用途:

* 過濾,整形,NAT和重定向中的源或者目的地址.
* NAT規則中的轉換地址.
* 重定向規則中的重定向地址.
* 過濾規則選項中 route-to, reply-to, 和 dup-to的目的地址.

表可以通過在pf.conf裏配置和使用pfctl生成。

配置

在pf.conf文件中, 表是使用table關鍵字創建出來的。下面的關鍵字必須在創建表時指定。

* constant - 這類表的內容一旦創建出來就不能被改變。如果這個屬性沒有指定,可以使用pfctl添加和刪除表裏的地址,即使系統是運行在2或者更高得安全級別上。
* persist - 即使沒有規則引用這類表,內核也會把它保留在內存中。如果這個屬性沒有指定,當最後引用它的規則被取消後內核自動把它移出內存。

實例:

table  { 192.0.2.0/24 }
table  const { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
table  persist

block in on fxp0 from { ,  } to any
pass in on fxp0 from  to any

地址也可以用“非”來進行修改,如:

table  { 192.0.2.0/24, !192.0.2.5 }

goodguys表將匹配除192.0.2.5外192.0.2.0/24網段得所有地址。

注意表名總是在符號得裏面。

表也可以由包含IP地址和網絡地址的文本文件中輸入:

table  persist file "/etc/spammers"

block in on fxp0 from  to any

文件 /etc/spammers 應該包含被阻塞的IP地址或者CIDR網絡地址,每個條目一行。以#開頭的行被認爲是註釋會被忽略。

用 pfctl 進行操作

表可以使用pfctl進行靈活的操作。例如,在上面產生的表中增加條目可以這樣寫:

# pfctl -t spammers -T add 218.70.0.0/16

如果這個表不存在,這樣會創建出這個表來。列出表中的內容可以這樣:

# pfctl -t spammers -T show

-v 參數也可以使用-Tshow 來顯示每個表的條目內容統計。要從表中刪除條目,可以這樣:

# pfctl -t spammers -T delete 218.70.0.0/16

指定地址

除了使用IP地址來指定主機外,也可以使用主機名。當主機名被解析成IP地址時,IPv4和IPv6地址都被插進規則中。IP地址也可以通過合法的接口名稱或者self關鍵字輸入表中,這樣的表會分別包含接口或者機器上(包括loopback地址)上配置的所有IP地址。

一個限制時指定地址0.0.0.0/0 以及 0/0在表中不能工作。替代方法是明確輸入該地址或者使用宏。

地址匹配

表中的地址查詢會匹配最接近的規則,比如:

table  { 172.16.0.0/16, !172.16.1.0/24, 172.16.1.100 }

block in on dc0 all
pass in on dc0 from  to any

任何自dc0上數據包都會把它的源地址和goodguys表中的地址進行匹配:

* 172.16.50.5 - 精確匹配172.16.0.0/16; 數據包符合可以通過
* 172.16.1.25 - 精確匹配!172.16.1.0/24; 數據包匹配表中的一條規則,但規則是“非”(使用“!”進行了修改);數據包不匹配表會被阻塞。
* 172.16.1.100 - 準確匹配172.16.1.100; 數據包匹配表,運行通過
* 10.1.4.55 - 不匹配表,阻塞。

編輯本段   回目錄    

PF防火牆 - 包過濾

PF防火牆簡介

包過濾是在數據包通過網絡接口時進行選擇性的運行通過或者阻塞。pf檢查包時使用的標準是基於的3層(IPV4或者IPV6)和4層(TCPUDPICMPICMPv6)包頭。最常用的標準是源和目的地址源和目的端口,以及協議

過濾規則集指定了數據包必須匹配的標準和規則集作用後的結果,在規則集匹配時通過或者阻塞。規則集由開始到結束順序執行。除非數據包匹配的規則包含quick關鍵字,否則數據包在最終執行動作前會通過所有的規則檢驗。最後匹配的規則具有決定性,決定了數據包最終的執行結果。存在一條潛在的規則是如果數據包和規則集中的所有規則都不匹配,則它會被通過。

規則語法

一般而言,最簡單的過濾規則語法是這樣的:

action direction [log] [quick] on interface [af] [proto protocol] \
from src_addr [port src_port] to dst_addr [port dst_port] \
[tcp_flags] [state]

action
數據包匹配規則時執行的動作,放行或者阻塞。放行動作把數據包傳遞給核心進行進一步出來,阻塞動作根據block-policy 選項指定的方法進行處理。默認的動作可以修改爲阻塞丟棄或者阻塞返回。
direction
數據包傳遞的方向,進或者出
log
指定數據包被pflogd( 進行日誌記錄。如果規則指定了keep state, modulate state, or synproxy state 選項,則只有建立了連接的狀態被日誌。要記錄所有的日誌,使用log-all
quick
如果數據包匹配的規則指定了quick關鍵字,則這條規則被認爲時最終的匹配規則,指定的動作會立即執行。
interface
數據包通過的網絡接口的名稱或組。組是接口的名稱但沒有最後的整數。比如pppfxp,會使得規則分別匹配任何ppp或者fxp接口上的任意數據包。
af
數據包的地址類型,inet代表Ipv4,inet6代表Ipv6。通常PF能夠根據源或者目標地址自動確定這個參數。
protocol
數據包的4層協議:
tcp
udp
icmp
icmp6
/etc/protocols中的協議名稱
0~255之間的協議號
使用列表的一系列協議.
src_addr, dst_addr
IP頭中的源/目標地址。地址可以指定爲:
單個的Ipv4或者Ipv6地址.
CIDR 網絡地址.
能夠在規則集載入時通過DNS解析到的合法的域名,IP地址會替代規則中的域名。
網絡接口名稱。網絡接口上配置的所有ip地址會替代進規則中。
帶有/掩碼(例如/24)的網絡接口的名稱。每個根據掩碼確定的CIDR網絡地址都會被替代進規則中。.
帶有()的網絡接口名稱。這告訴PF如果網絡接口的IP地址改變了,就更新規則集。這個對於使用DHCP或者撥號來獲得IP地址的接口特別有用,IP地址改變時不需要重新載入規則集。
帶有如下的修飾詞的網絡接口名稱:
o :network - 替代CIDR網絡地址段 (例如:192.168.0.0/24)
o :broadcast - 替代網絡廣播地址(例如:192.168.0.255)
o :peer - 替代點到點鏈路上的ip地址。

另外,:0修飾詞可以附加到接口名稱或者上面的修飾詞後面指示PF在替代時不包括網絡接口的其餘附加(alias)地址。這些修飾詞也可以在接口名稱在括號()內時使用。例如:fxp0:network:0

表.
上面的所有項但使用!(非)修飾詞
使用列表的一系列地址.
關鍵字 any 代表所有地址
關鍵字 all 是 from any to any的縮寫。
src_port, dst_port
4層數據包頭中的源/目標端口。端口可以指定爲:
1 到 65535之間的整數
/etc/services中的合法服務名稱
使用列表的一系列端口
一個範圍:
o != (不等於)
o  (大於)
o = (大於等於)
o > (反轉範圍)

最後2個是二元操作符(他們需要2個參數),在範圍內不包括參數。

o : (inclusive range)

inclusive range 也是二元操作符但範圍內包括參數。

tcp_flags
指定使用TCP協議時TCP頭中必須設定的標記。 標記指定的格式是: flags check/mask. 例如: flags S/SA -這指引PF只檢查S和A(SYN and ACK)標記,如果SYN標記是“on”則匹配。

state
指定狀態信息在規則匹配時是否保持。
keep state - 對 TCP, UDP, ICMP起作用
modulate state - 只對 TCP起作用. PF會爲匹配規則的數據包產生強壯的初始化序列號。
synproxy state - 代理外來的TCP連接以保護服務器不受TCP SYN FLOODs欺騙。這個選項包含了keep state 和 modulate state 的功能。

默認拒絕

按照慣例建立防火牆時推薦執行的是默認拒絕的方法。也就是說先拒絕所有的東西,然後有選擇的允許某些特定的流量通過防火牆。這個方法之所以是推薦的是因爲它寧可失之過於謹慎(也不放過任何風險),而且使得編寫規則集變得簡單。

產生一個默認拒絕的過濾規則,開始2行過濾規則必須是:

block in all
block out all

這會阻塞任何通信方在任何方向上進入任意接口的所有流量。

通過流量

流量必須被明確的允許通過防火牆或者被默認拒絕的策略丟棄。這是數據包標準如源/目的端口,源/目的地址和協議開始活動的地方。無論何時數據包在被允許通過防火牆時規則都要設計的儘可能嚴厲。這是爲了保證設計中的流量,也只有設計中的流量可以被允許通過。

實例:

# 允許本地網絡192.168.0.0/24流量通過dc0接口進入訪問openbsd機器的IP地址
#192.168.0.1,同時也允許返回的數據包從dc0接口出去。
pass in on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24

# Pass TCP traffic in on fxp0 to the web server running on the
# OpenBSD machine. The interface name, fxp0, is used as the
# destination address so that packets will only match this rule if
# they‘re destined for the OpenBSD machine.
pass in on fxp0 proto tcp from any to fxp0 port www

quick 關鍵字

每個數據包都要按自上至下的順序按規則進行過濾。默認情況下,數據包被標記爲通過,這個可以被任一規則改變,在到達最後一條規則前可以被來回改變多次,最後的匹配規則是“獲勝者”。存在一個例外是:過濾規則中的quick關鍵字具有取消進一步往下處理的作用,使得規則指定的動作馬上執行。看一下下面的例子:

錯誤:

block in on fxp0 proto tcp from any to any port ssh
pass in all

在這樣的條件下,block行會被檢測,但永遠也不會有效果,因爲它後面的一行允許所有的流量通過。

正確:

block in quick on fxp0 proto tcp from any to any port ssh
pass in all

這些規則執行的結果稍有不同,如果block行被匹配,由於quick選項的原因,數據包會被阻塞,而且剩下的規則也會被忽略。

狀態保持

PF一個非常重要的功能是“狀態保持”或者“狀態檢測”。狀態檢測指PF跟蹤或者處理網絡連接狀態的能力。通過存貯每個連接的信息到一個狀態表中,PF能夠快速確定一個通過防火牆的數據包是否屬於已經建立的連接。如果是,它會直接通過防火牆而不用再進行規則檢驗。

狀態保持有許多的優點,包括簡單的規則集和優良的數據包處理性能。
PF is able to match packets moving in either direction to state table entries meaning that filter rules which pass returning trafficdon‘t need to be written. 
並且,由於數據包匹配狀態連接時不再進行規則集的匹配檢測,PF用於處理這些數據包的時間大爲減少。

當一條規則使用了keep state選項,第一個匹配這條規則的數據包在收發雙方之間建立了一個狀態。現在,不僅發送者到接收者之間的數據包匹配這個狀態繞過規則檢驗,而且接收者回復發送者的數據包也是同樣的。例如:

pass out on fxp0 proto tcp from any to any keep state

這允許fxp0接口上的任何TCP流量通過,並且允許返回的流量通過防火牆。狀態保持是一個非常有用的特性,由於狀態查詢比使用規則進行數據包檢驗快的多,因此它可以大幅度提高防火牆的性能。

狀態調整選項和狀態保持的功能在除了僅適用於TCP數據包以爲完全相同。在使用狀態調整時,輸入連接的初始化序列號(ISN)是隨機的,這對於保護某些選擇ISN存在問題的操作系統的連接初始化非常有用。從openbsd 3.5開始,狀態調整選項可以應用於包含非TCP的協議規則。

對輸出的TCP, UDP, ICMP數據包保持狀態,並且調整TCP ISN

pass out on fxp0 proto { tcp, udp, icmp } from any to any modulate state

狀態保持的另一個優點是ICMP通信流量可以直接通過防火牆。例如,如果一個TCP連接使用了狀態保持,當和這個TCP連接相關的ICMP數據包到來時,它會自動找到合適的狀態記錄,直接通過防火牆。

狀態記錄的範圍被state-policy runtime選項總體控制,也能基於單條規則由if-bound, group-bound, 和 floating state選項關鍵字設定。這些針對單條規則的關鍵字在使用時具有和state-policy選項同樣的意義。例如:

pass out on fxp0 proto { tcp, udp, icmp } from any to any modulate state (if-bound)

狀態規則指示爲了使數據包匹配狀態條目,它們必須通過fxp0網絡接口傳遞。

需要注意的是,nat,binat,rdr規則隱含在連接通過過濾規則集審覈的過程中產生匹配連接的狀態。

UDP狀態保持

“不能爲UDP產生狀態,因爲UDP是無狀態的協議”。確實,UDP通信會話沒有狀態的概念(明確的開始和結束通信),這絲毫不影響PF爲 UDP會話產生狀態的能力。對於沒有開始和結束數據包的協議,PF僅簡單追蹤匹配的數據部通過的時間。如果到達超時限制,狀態被清除,超時的時間值可以在pf.conf配置文件中設定。

TCP 標記

基於標記的TCP包匹配經常被用於過濾試圖打開新連接的TCP數據包。TCP標記和他們的意義如下所列:

* F : FIN - 結束; 結束會話
* S : SYN - 同步; 表示開始會話請求
* R :RST - 復位;中斷一個連接
* P : PUSH - 推送; 數據包立即發送
* A : ACK - 應答
* U : URG - 緊急
* E : ECE - 顯式擁塞提醒迴應
* W : CWR - 擁塞窗口減少

要使PF在規則檢查過程中檢查TCP標記,flag關鍵需按如下語法設置。

flags check/mask

mask部分告訴PF僅檢查指定的標記,check部分說明在數據包頭中哪個標記設置爲“on”纔算匹配。

pass in on fxp0 proto tcp from any to any port ssh flags S/SA

上面的規則通過的帶SYN標記的TCP流量僅查看SYN和ACK標記。帶有SYN和ECE標記的數據包會匹配上面的規則,而帶有SYN和ACK的數據包或者僅帶有ACK的數據包不會匹配。

注意:在前面的openbsd版本中,下面的語法是支持的:

. . . flags S

現在,這個不再支持,mask必須被說明。

標記常常和狀態保持規則聯合使用來控制創建狀態條目:

pass out on fxp0 proto tcp all flags S/SA keep state

這條規則允許爲所有輸出中帶SYN和ACK標記的數據包中的僅帶有SYN標記的TCP數據包創建狀態。

使用標記時必須小心,理解在做什麼和爲什麼這樣做。小心聽取建議,因爲相當多的建議時不好的。一些人建議創建狀態“只有當SYN標記設定而沒有其他標記”時,這樣的規則如下:
. . . flags S/FSRPAUEW 糟糕的主意!!

這個理論是,僅爲TCP開始會話時創建狀態,會話會以SYN標記開始,而沒有其他標記。問題在於一些站點使用ECN標記開始會話,而任何使用ECN連接你的會話都會被那樣的規則拒絕。比較好的規則是:

. . . flags S/SAFR

這個經過實踐是安全的,如果流量進行了整形也沒有必要檢查FIN和RST標記。整形過程會讓PF丟棄帶有非法TCP標記的進入數據包(例如SYN和FIN以及SYN和RST)。強烈推薦總是進行流量整形:

scrub in on fxp0
.
.
.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA \
keep state

TCP SYN 代理

通過,當客戶端向服務器初始化一個TCP連接時,PF會在二者直接傳遞握手數據包。然而,PF具有這樣的能力,就是代理握手。使用握手代理,PF自己會和客戶端完成握手,初始化和服務器的握手,然後在二者之間傳遞數據。這樣做的優點是在客戶端完成握手之前,沒有數據包到達服務器。這樣就消沉了TCP SYN FLOOD欺騙影響服務器的問題,因爲進行欺騙的客戶端不會完成握手。

TCP SYN 代理在規則中使用synproxy state關鍵字打開。例如:

pass in on $ext_if proto tcp from any to $web_server port www \
flags S/SA synproxy state

這樣, web服務器的連接由PF進行TCP代理。

由於synproxy state工作的方式,它具有keep state 和 modulate state一樣的功能。

如果PF工作在橋模式下,SYN代理不會起作用。

阻塞欺騙數據包

地址欺騙是惡意用戶爲了隱藏他們的真實地址或者假冒網絡上的其他節點而在他們傳遞的數據包中使用虛假的地址。一旦實施了地址欺騙,他們可以隱蔽真實地址實施網絡攻擊或者獲得僅限於某些地址的網絡訪問服務。

PF通過antispoof關鍵字提供一些防止地址欺騙的保護。

antispoof [log] [quick] for interface [af]

log
指定匹配的數據包應該被pflogd進行日誌記錄
quick
如果數據包匹配這條規則,則這是最終的規則,不再進行其他規則集的檢查。
interface
激活要進行欺騙保護的網絡接口。也可以是接口的列表。
af
激活進行欺騙保護的地址族,inet代表Ipv4,inet6代表Ipv6。

實例:

antispoof for fxp0 inet

當規則集載入時,任何出現了antispoof關鍵字的規則都會擴展成2條規則。假定接口fxp0具有ip地址10.0.0.1和子網掩碼255.255.255.0(或者/24),上面的規則會擴展成:

block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any

這些規則實現下面的2個目的:

* 阻塞任何不是由fxp0接口進入的10.0.0.0/24網絡的流量。由於10.0.0.0/24的網絡是在fxp0接口,具有這樣的源網絡地址的數據包絕不應該從其他接口上出現。
* 阻塞任何由10.0.0.1即fxp0接口的IP地址的進入流量。主機絕對不會通過外面的接口給自己發送數據包,因此任何進入的流量源中帶有主機自己的IP地址都可以認爲是惡意的!

注意:antispoof規則擴展出來的過濾規則會阻塞loopback接口上發送到本地地址的數據包。這些數據包應該明確的配置爲允許通過。例如:

pass quick on lo0 all

antispoof for fxp0 inet

使用antispoof應該僅限於已經分配了IP地址的網絡接口,如果在沒有分配IP地址的網絡接口上使用,過濾規則會擴展成:

block drop in on ! fxp0 inet all
block drop in inet all

這樣的規則會存在阻塞所有接口上進入的所有流量的危險。

被動操作系統識別

被動操作系統識別是通過基於遠端主機TCP SYN數據包中某些特徵進行操作系統被動檢測的技術。這些信息可以作爲標準在過濾規則中使用。

PF檢測遠端操作系統是通過比較TCP SYN數據包中的特徵和已知的特徵文件對照來確定的,特徵文件默認是/etc/pf.os。如果PF起作用,可是使用下面的命令查看當前的特徵列表。

# pfctl -s osfp

在規則集中,特徵可以指定爲OS類型,版本,或者子類型/補丁級別。這些條目在上面的pfctl命令中有列表。要在過濾規則中指定特徵,需使用os關鍵字:

pass in on $ext_if any os OpenBSD keep state
block in on $ext_if any os "Windows 2000"
block in on $ext_if any os "Linux 2.4 ts"
block in on $ext_if any os unknown

指定的操作系統類型unknow允許匹配操作系統未知的數據包。

注意以下的內容::

*操作系統識別偶爾會出錯,因爲存在欺騙或者修改過的使得看起來象某個操作系統得數據包。
* 某些修改或者打過補丁得操作系統會改變棧得行爲,導致它或者和特徵文件不符,或者符合了另外得操作系統特徵。
* OSFP 僅對TCP SYN數據包起作用,它不會對其他協議或者已經建立得連接起作用。

IP 選項

默認情況下,PF阻塞帶有IP選項得數據包。這可以使得類似nmap得操作系統識別軟件工作困難。如果應用程序需要通過這樣的數據包,例如多播或者IGMP,可以使用allow-opts關鍵字

pass in quick on fxp0 all allow-opts

過濾規則實例

下面是過濾規則得實例。運行PF的機器充當防火牆,在一個小得內部網絡和因特網之間。只列出了過濾規則,queueing, nat, rdr,等等沒有在實例中列出。

ext_if = "fxp0"
int_if = "dc0"
lan_net = "192.168.0.0/24"

# scrub incoming packets
scrub in all

# setup a default deny policy
block in all
block out all

# pass traffic on the loopback interface in either direction
pass quick on lo0 all

# activate spoofing protection for the internal interface.
antispoof quick for $int_if inet

# only allow ssh connections from the local network if it‘s from the
# trusted computer, 192.168.0.15. use "block return" so that a TCP RST is
# sent to close blocked connections right away. use "quick" so that this
# rule is not overridden by the "pass" rules below.
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
to $int_if port ssh flags S/SA

# pass all traffic to and from the local network
pass in on $int_if from $lan_net to any
pass out on $int_if from any to $lan_net

# pass tcp, udp, and icmp out on the external (Internet) interface.
# keep state on udp and icmp and modulate state on tcp.
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state

# allow ssh connections in on the external interface as long as they‘re
# NOT destined for the firewall (i.e., they‘re destined for a machine on
# the local network). log the initial packet so that we can later tell
# who is trying to connect. use the tcp syn proxy to proxy the connection.
pass in log on $ext_if proto tcp from any to { !$ext_if, !$int_if } \
port ssh flags S/SA synproxy state

編輯本段   回目錄    

PF防火牆 - 網絡地址轉換(NAT)

PF防火牆簡介
網絡地址轉換是映射整個網絡(或者多個網絡)到單個IP地址的方法。當ISP分配的IP地址數目少於要連上互聯網的計算機數目時,NAT是必需的。NAT在RFC1631中描述。

NAT允許使用RFC1918中定義的保留地址族。典型情況下,內部網絡可以下面的地址族:
10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
192.168.0.0/16 (192.168.0.0 - 192.168.255.255)

擔任NAT任務的操作系統必須至少要2塊網卡,一塊連接到因特網,另一塊連接內部網絡。NAT會轉換內部網絡的所有請求,使它們看起來象是來自進行NAT工作的主機系統。

NAT如何工作

當內部網絡的一個客戶端連接因特網上的主機時,它發送目的是那臺主機的IP數據包。這些數據包包含了達到連接目的的所有信息。NAT的作用和這些信息相關。

* 源 IP 地址 (例如, 192.168.1.35)
* 源 TCP 或者 UDP 端口 (例如, 2132)

當數據包通過NAT網關時,它們會被修改,使得數據包看起來象是從NAT網關自己發出的。NAT網關會在它的狀態表中記錄這個改變,以便:
a)將返回的數據包反向轉換
b)確保返回的數據包能通過防火牆而不會被阻塞。

例如,會發生下面的改變:

* 源 IP: 被網關的外部地址所替換(例如, 24.5.0.5)
* 源端口:被隨機選擇的網關沒有在用的端口替換 (例如, 53136)

內部主機和因特網上的主機都不會意識到發生了這個轉變步驟。對於內部主機,NAT系統僅僅是個因特網網關,對於因特網上的主機,數據包看起來直接來自NAT系統,它完全不會意識到內部工作站的存在。

當因特網網上的主機迴應內部主機的數據包時,它會使用NAT網關機器的外部地址和轉換後的端口。然後NAT網關會查詢狀態表來確定返回的數據包是否匹配某個已經建立的連接。基於IP地址和端口的聯合找到唯一匹配的記錄告訴PF這個返回的數據包屬於內部主機192.168.1.35。然後PF會進行和出去的數據包相反的轉換過程,將返回的數據包傳遞給內部主機。

ICMP數據包的轉換也是類似的,只是不進行源端口的修改。

PF防火牆NAT和包過濾

注意:轉換後的數據包仍然會通過過濾引擎,根據定義的過濾規則進行阻塞或者通過。唯一的例外是如果nat規則中使用了pass關鍵字,會使得經過nat的數據包直接通過過濾引擎。

還要注意由於轉換是在過濾之前進行,過濾引擎所看到的是上面“nat如何工作”中所說的經過轉換後的ip地址和端口的數據包。

IP 轉發

由於NAT經常在路由器和網關上使用,因此IP轉發是需要的,使得數據包可以在UNIX機器的不同網絡接口間傳遞。IP轉發可以通過sysctl命令打開:

# sysctl -w net.inet.ip.forwarding=1
# sysctl -w net.inet6.ip6.forwarding=1 (if using IPv6)

要使這個變化永久生效,可以增加如下行到/etc/sysctl.conf文件中:

net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1

這些行是本來就存在的,但默認安裝中被#前綴註釋掉了。刪除#,保存文件,IP轉發在機器重啓後就會發生作用。

配置NAT

一般的NAT規則格式在pf.conf文件中是這個樣子:

nat [pass] on interface [af] from src_addr [port src_port] to \
dst_addr [port dst_port] -> ext_addr [pool_type] [static-port]

nat
開始NAT規則的關鍵字。
pass
使得轉換後的數據包完全繞過過濾規則。
interface
進行數據包轉換的網絡接口。
af
地址類型,inet代表Ipv4,inet6代表Ipv6。PF通常能根據源/目標地址自動確定這個參數。
src_addr
被進行轉換的IP頭中的源(內部)地址。源地址可以指定爲:
單個的Ipv4或者Ipv6地址.
CIDR 網絡地址.
能夠在規則集載入時通過DNS解析到的合法的域名,IP地址會替代規則中的域名。
網絡接口名稱。網絡接口上配置的所有ip地址會替代進規則中。
帶有/掩碼(例如/24)的網絡接口的名稱。每個根據掩碼確定的CIDR網絡地址都會被替代進規則中。.
帶有()的網絡接口名稱。這告訴PF如果網絡接口的IP地址改變了,就更新規則集。這個對於使用DHCP或者撥號來獲得IP地址的接口特別有用,IP地址改變時不需要重新載入規則集。
帶有如下的修飾詞的網絡接口名稱:
o :network - 替代CIDR網絡地址段 (例如, 192.168.0.0/24)
o :broadcast - 替代網絡廣播地址(例如, 192.168.0.255)
o :peer - 替代點到點鏈路上的ip地址。

另外,:0修飾詞可以附加到接口名稱或者上面的修飾詞後面指示PF在替代時不包括網絡接口的其餘附加(alias)地址。這些修飾詞也可以在接口名稱在括號()內時使用。例如:fxp0:network:0

表.
上面的所有項但使用!(非)修飾詞
使用列表的一系列地址.
關鍵字 any 代表所有地址
關鍵字 all 是 from any to any的縮寫。

src_port
4層數據包頭中的源端口。端口可以指定爲:
1 到 65535之間的整數
/etc/services中的合法服務名稱
使用列表的一系列端口
一個範圍:
o != (不等於)
o  (大於)
o = (大於等於)
o > (反轉範圍)

最後2個是二元操作符(他們需要2個參數),在範圍內不包括參數。

o : (inclusive range)

inclusive range 也是二元操作符但範圍內包括參數。

Port選項在NAT規則中通常不使用,因爲目標通常會NAT所有的流量而不過端口是否在使用。
dst_addr
被轉換數據包中的目的地址。目的地址類型和源地址相似。
dst_port
4層數據包頭中的目的目的端口,目的端口類型和源端口類型相似。
ext_addr
NAT網關上數據包被轉換後的外部地址。外部地址可以是:
單個的Ipv4或者Ipv6地址.
CIDR 網絡地址.
能夠在規則集載入時通過DNS解析到的合法的域名,IP地址會替代規則中的域名。
網絡接口名稱。網絡接口上配置的所有ip地址會替代進規則中。
帶有/掩碼(例如/24)的網絡接口的名稱。每個根據掩碼確定的CIDR網絡地址都會被替代進規則中。.
帶有()的網絡接口名稱。這告訴PF如果網絡接口的IP地址改變了,就更新規則集。這個對於使用DHCP或者撥號來獲得IP地址的接口特別有用,IP地址改變時不需要重新載入規則集。
帶有如下的修飾詞的網絡接口名稱:
o :network - 替代CIDR網絡地址段 (例如, 192.168.0.0/24)
o :broadcast - 替代網絡廣播地址(例如, 192.168.0.255)
o :peer - 替代點到點鏈路上的ip地址。

另外,:0修飾詞可以附加到接口名稱或者上面的修飾詞後面指示PF在替代時不包括網絡接口的其餘附加(alias)地址。這些修飾詞也可以在接口名稱在括號()內時使用。例如:fxp0:network:0
使用列表的一系列地址.
pool_type
指定轉換後的地址池的類型
static-port
告訴PF不要轉換TCP和UDP數據包中的源端口

這條規則最簡單的形式如下:

nat on tl0 from 192.168.1.0/24 to any -> 24.5.0.5

這條規則是說對從tl0網絡接口上到來的所有192.168.1.0/24網絡的數據包進行NAT,將源地址轉換爲24.5.0.5。

儘管上面的規則是正確的,但卻不是推薦的形式。因爲維護起來有困難,當內部或者外部網絡有變化時都要修改這一行。比較一下下面這條比較容易維護的規則:(tl0時外部,dc0是內部):

nat on tl0 from dc0:network to any -> tl0

優點是相當明顯的,可以任意改變2個接口的IP地址而不用改變這條規則。

象上面這樣在地址轉換中使用接口名稱時,IP地址在pf.conf文件載入時確定,並不是憑空的。如果使用DHCP還配置外部地址,這會存在問題。如果分配的IP地址改變了,NAT仍然會使用舊的IP地址轉換出去的數據包。這會導致對外的連接停止工作。爲解決這個問題,應該給接口名稱加上括號,告訴PF自動更新轉換地址。

nat on tl0 from dc0:network to any -> (tl0)

這個方法對IPv4 和 IPv6地址都用效。

PF防火牆雙向映射 (1:1 映射)

雙向映射可以通過使用binat規則建立。Binat規則建立一個內部地址和外部地址一對一的映射。這會很有用,比如,使用獨立的外部IP地址用內部網絡裏的機器提供web服務。從因特網到來連接外部地址的請求被轉換到內部地址,同時由(內部)web服務器發起的連接(例如DNS查詢)被轉換爲外部地址。和NAT規則不過,binat規則中的tcp和udp端口不會被修改。


例如:

web_serv_int = "192.168.1.100"
web_serv_ext = "24.5.0.6"

binat on tl0 from $web_serv_int to any -> $web_serv_ext

轉換規則例外設置

使用no關鍵字可以在轉換規則中設置例外。例如,如果上面的轉換規則修改成這樣:

no nat on tl0 from 192.168.1.10 to any
nat on tl0 from 192.168.1.0/24 to any -> 24.2.74.79

則除了192.168.1.10以外,整個192.168.1.0/24網絡地址的數據包都會轉換爲外部地址24.2.74.79。

注意第一條匹配的規則起了決定作用,如果是匹配有no的規則,數據包不會被轉換。No關鍵字也可以在binat和rdr規則中使用。

檢查 NAT 狀態

要檢查活動的NAT轉換可以使用pfctl帶-s state 選項。這個選項列出所有當前的NAT會話。

# pfctl -s state
fxp0 TCP 192.168.1.35:2132 -> 24.5.0.5:53136 -> 65.42.33.245:22 TIME_WAIT:TIME_WAIT
fxp0 UDP 192.168.1.35:2491 -> 24.5.0.5:60527 -> 24.2.68.33:53 MULTIPLE:SINGLE

解釋 (對第一行):

fxp0
顯示狀態綁定的接口。如果狀態是浮動的,會出現self字樣。

TCP
連接使用的協議。

192.168.1.35:2132
內部網絡中機器的IP地址 (192.168.1.35),源端口(2132)在地址後顯示,這個也是被替換的IP頭中的地址。 of the machine on the internal network. The
source port (2132) is shown after the address. This is also the address
that is replaced in the IP header.

24.5.0.5:53136
IP 地址 (24.5.0.5) 和端口 (53136) 是網關上數據包被轉換後的地址和端口。

65.42.33.245:22
IP 地址 (65.42.33.245) 和端口 (22) 是內部機器要連接的地址和端口。

TIME_WAIT:TIME_WAIT
這表明PF認爲的目前這個TCP連接的狀態。

編輯本段   回目錄    

PF防火牆 - 重定向 (端口轉發)

PF防火牆簡介

如果在辦公地點應用了NAT,內部網所有的機器都可以訪問因特網。但如何讓NAT網關後面的機器能夠被從外部訪問?這就是重定向的來源。重定向允許外來的流量發送到NAT網關後面的機器。

看個例子:

rdr on tl0 proto tcp from any to any port 80 -> 192.168.1.20

這一行重定向了TCP端口80(web服務器)流量到內部網絡地址192.168.1.20。因此,即使192.168.1.20在網關後面的內部網絡,外部仍然能夠訪問它。

上面rdr行中from any to any部分非常有用。如果明確知道哪些地址或者子網被允許訪問web服務器的80端口,可以在這部分嚴格限制:

rdr on tl0 proto tcp from 27.146.49.0/24 to any port 80 -> 192.168.1.20

這樣只會重定向指定的子網。注意這表明可以重定向外部不同的訪問主機到網關後面不同的機器上。這非常有用。例如,如果知道遠端的用戶連接上來時使用的IP地址,可以讓他們使用網關的IP地址和端口訪問他們各自的桌面計算機。

rdr on tl0 proto tcp from 27.146.49.14 to any port 80 -> \
192.168.1.20
rdr on tl0 proto tcp from 16.114.4.89 to any port 80 -> \
192.168.1.22
rdr on tl0 proto tcp from 24.2.74.178 to any port 80 -> \
192.168.1.23

重定向和包過濾

注意:轉換後的數據包仍然會通過過濾引擎,根據定義的過濾規則進行阻塞或者通過。唯一的例外是如果rdr規則中使用了pass關鍵字,會使得重定向的數據包直接通過過濾引擎。

還要注意由於轉換是在過濾之前進行,過濾引擎所看到的是在匹配rdr規則經過轉換後的目標ip地址和端口的數據包。

* 192.0.2.1 - 因特網上的主機
* 24.65.1.13 - openbsd路由器的外部地址
* 192.168.1.5 - web服務器的內部IP地址

PF防火牆重定向規則:

rdr on tl0 proto tcp from 192.0.2.1 to 24.65.1.13 port 80 \
-> 192.168.1.5 port 8000

數據包在經過rdr規則前的模樣:

* 源地址: 192.0.2.1
* 源端口: 4028 (由操作系統任意選擇)
* 目的地址: 24.65.1.13
* 目的端口: 80

數據包經過rdr規則後的模樣:

* 源地址: 192.0.2.1
* 源端口: 4028
* 目的地址: 192.168.1.5
* 目的: 8000

過濾引擎看見的IP數據包時轉換髮生之後的情況。

安全隱患

重定向確實存在安全隱患。在防火牆上開了一個允許流量進入內部網絡的洞,被保護的網絡安全潛在的受到了威脅!例如,如果流量被轉發到了內部的web服務器,而web服務器上允許的守護程序或者CGI腳本程序存在漏洞,則這臺服務器存在會被因特網網上的入侵者攻擊危險。如果入侵者控制了這臺機器,就有了進入內部網絡的通道,僅僅是因爲這種流量是允許通過防火牆的。

這種風險可以通過將允許外部網絡訪問的系統限制在一個單獨的網段中來減小。這個網段通常也被稱爲非軍事化區域(DMZ)或者私有服務網絡(PSN)。通過這個方法,如果web服務器被控制,通過嚴格的過濾進出DMZ/PSN的流量,受影響的系統僅限於DMZ/PSN網段。

重定向和反射

通常,重定向規則是用來將因特網上到來的連接轉發到一個內部網絡或者局域網的私有地址。例如:

server = 192.168.1.40

rdr on $ext_if proto tcp from any to $ext_if port 80 -> $server \
port 80

但是,當一個重定向規則被從局域網上的客戶端進行測試時,它不會正常工作。這是因爲重定向規則僅適用於通過指定端口($ext_if,外部接口,在上面的例子中)的數據包。從局域網上的主機連接防火牆的外部地址,並不意味着數據包會實際的通過外部接口。防火牆上的TCP/IP棧會把到來的數據包的目的地址在通過內部接口時與它自己的IP地址或者別名進行對比檢測。那樣的數據包不會真的通過外部接口,棧在任何情況下也不會建立那樣的通道。因而,PF永遠也不會在外部接口上看到那些數據包,過濾規則由於指定了外部接口也不會起作用。

指定第二條針對內部接口的也達不到預想的效果。當本地的客戶端連接防火牆的外部地址時,初始化的TCP握手數據包是通過內部接口到達防火牆的。重定向規則確實起作用了,目標地址被替換成了內部服務器,數據包通過內部接口轉發到了內部的服務器。但源地址沒有進行轉換,仍然包含的是本地客戶端的IP地址,因此服務器把它的迴應直接發送給了客戶端。防火牆永遠收不到應答不可能返回客戶端信息,客戶端收到的應答不是來自它期望的源(防火牆)會被丟棄,TCP握手失敗,不能建立連接。

當然,局域網裏的客戶端仍然會希望象外部客戶一樣透明的訪問這臺內部服務器。有如下的方法解決這個問題:

水平分割 DNS

存在這樣的可能性,即配置DNS服務器使得它回答內部主機的查詢和回答外部主機的查詢不一樣,因此內部客戶端在進行名稱解析時會收到內部服務器的地址。它們直接連接到內部服務器,防火牆根本不牽扯。這會降低本地流量,因爲數據包不會被送到防火牆。

將服務器移到獨立的本地網絡

增加單獨的網絡接口卡到防火牆,把本地的服務器從和客戶端同一個網段移動到專用的網段(DMZ)可以讓本地客戶端按照外部重定向連接的方法一樣重定向。使用單獨的網段有幾個優點,包括和保留的內部主機隔離增加了安全性;服務器(我們的案例中可以從因特網訪問)一旦被控制,它不能直接存取本地網絡因爲所有的連接都必須通過防火牆。

TCP 代理

一般而言,TCP代理可以在防火牆上設置,監聽要轉發的端口或者將內部接口上到來的連接重定向到它監聽的端口。當本地客戶端連接防火牆時,代理接受連接,建立到內部服務器的第二條連接,在通信雙方間進行數據轉發。

簡單的代理可以使用inetdnc建立。下面的/etc/inetd.conf中的條目建立一個監聽套接字綁定到lookback地址(127.0.0.1)和端口5000。連接被轉發到服務器192.168.1.10的80端口。

127.0.0.1:5000 stream tcp nowait nobody /usr/bin/nc nc -w \
20 192.168.1.10 80

下面的重定向規則轉發內部接口的80端口到代理:

rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
127.0.0.1 port 5000

RDR 和 NAT 結合

通過對內部接口增加NAT規則,上面說的轉換後源地址不變的問題可以解決。

rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
$server
no nat on $int_if proto tcp from $int_if to $int_net
nat on $int_if proto tcp from $int_net to $server port 80 -> \
$int_if

這會導致由客戶端發起的初始化連接在收到內部接口的返回數據包時轉換回來,客戶端的源ip地址被防火牆的內部接口地址代替。內部服務器會迴應防火牆的內部接口地址,在轉發給本地客戶端時可以反轉NAT和RDR。這個結構是非常複雜的,因爲它爲每個反射連接產生了2個單獨的狀態。必須小心配置防止NAT規則應用到了其他流量,例如連接由外部發起(通過其他的重定向)或者防火牆自己。注意上面的rdr規則會導致TCP/IP棧看到來自內部接口帶有目的地址是內部網絡的數據包。

編輯本段   回目錄    

PF防火牆 - 規則生成捷徑

簡介

PF提供了許多方法來進行規則集的簡化。一些好的例子是使用宏和列表。另外,規則集的語言或者語法也提供了一些使規則集簡化的捷徑。首要的規則是,規則集越簡單,就越容易理解和維護。

使用宏

宏是非常有用的,因爲它提供了硬編碼地址,端口號,接口名稱等的可選替代。在一個規則集中,服務器的IP地址改變了?沒問題,僅僅更新一下宏,不需要弄亂花費了大量時間和精力建立的規則集。

通常的慣例是在PF規則集中定義每個網絡接口的宏。如果網卡需要被使用不同驅動的卡取代,例如,用intel代替3com,可以更新宏,過濾規則集會和以前功能一樣。另一個優點是,如果在多臺機器上安裝同樣的規則集,某些機器會有不同的網卡,使用宏定義網卡可以使的安裝的規則集進行最少的修改。使用宏來定義規則集中經常改變的信息,例如端口號,IP地址,接口名稱等等,建議多多實踐!

# define macros for each network interface
IntIF = "dc0"
ExtIF = "fxp0"
DmzIF = "fxp1"

另一個慣例是使用宏來定義IP地址和網絡,這可以大大減輕在IP地址改變時對規則集的維護。

# define our networks
IntNet = "192.168.0.0/24"
ExtAdd = "24.65.13.4"
DmzNet = "10.0.0.0/24"

如果內部地址擴展了或者改到了一個不同的IP段,可以更新宏爲:

IntNet = "{ 192.168.0.0/24, 192.168.1.0/24 }"

當這個規則集重新載入時,任何東西都跟以前一樣。

使用列表

來看一下一個規則集中比較好的例子使得RFC1918定義的內部地址不會傳送到因特網上,如果發生傳送的事情,可能導致問題。

block in quick on tl0 inet from 127.0.0.0/8 to any
block in quick on tl0 inet from 192.168.0.0/16 to any
block in quick on tl0 inet from 172.16.0.0/12 to any
block in quick on tl0 inet from 10.0.0.0/8 to any
block out quick on tl0 inet from any to 127.0.0.0/8
block out quick on tl0 inet from any to 192.168.0.0/16
block out quick on tl0 inet from any to 172.16.0.0/12
block out quick on tl0 inet from any to 10.0.0.0/8

看看下面更簡單的例子:

block in quick on tl0 inet from { 127.0.0.0/8, 192.168.0.0/16, \
172.16.0.0/12, 10.0.0.0/8 } to any
block out quick on tl0 inet from any to { 127.0.0.0/8, \
192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }

這個規則集從8行減少到2行。如果聯合使用宏,還會變得更好:

NoRouteIPs = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
10.0.0.0/8 }"
ExtIF = "tl0"
block in quick on $ExtIF from $NoRouteIPs to any
block out quick on $ExtIF from any to $NoRouteIPs

注意雖然宏和列表簡化了pf.conf文件,但是實際是這些行會被pfctl(8)擴展成多行,因此,上面的例子實際擴展成下面的規則:

block in quick on tl0 inet from 127.0.0.0/8 to any
block in quick on tl0 inet from 192.168.0.0/16 to any
block in quick on tl0 inet from 172.16.0.0/12 to any
block in quick on tl0 inet from 10.0.0.0/8 to any
block out quick on tl0 inet from any to 10.0.0.0/8
block out quick on tl0 inet from any to 172.16.0.0/12
block out quick on tl0 inet from any to 192.168.0.0/16
block out quick on tl0 inet from any to 127.0.0.0/8

可以看到,PF擴展僅僅是簡化了編寫和維護pf.conf文件,實際並不簡化pf(4)對於規則的處理過程。

宏不僅僅用來定義地址和端口,它們在PF的規則文件中到處都可以用:

pre = "pass in quick on ep0 inet proto tcp from "
post = "to any port { 80, 6667 } keep state"

# David‘s classroom
$pre 21.14.24.80 $post

# Nick‘s home
$pre 24.2.74.79 $post
$pre 24.2.74.178 $post

擴展後:

pass in quick on ep0 inet proto tcp from 21.14.24.80 to any \
port = 80 keep state
pass in quick on ep0 inet proto tcp from 21.14.24.80 to any \
port = 6667 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.79 to any \
port = 80 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.79 to any \
port = 6667 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.178 to any \
port = 80 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.178 to any \
port = 6667 keep state

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章