NAT&PF server in FREEBSD

Hsin
Hsin
Sep 4, 2018 · 2 min read

ENVIRONMENT

  • freebsd 11.2
  • one network interface controller with two ip (one public ip and one private ip)
ifconfig_bge0_alias0="inet 192.168.1.100 netmask 255.255.255.0"

STEP

1. edit /etc/rc.conf

#pf
pf_enable="YES" #啟動PF
pflog_enable="YES" #PF log啟動
pflog_logfile="/var/log/pflog"
#nat
gateway_enable="YES" #gateway啟動,若要做NAT時要開

2. edit /etc/pf.conf

#===========macro==============
ext_if="bge0" #網卡名稱
lan_net="192.168.1.100/24" #內網
tcp_ports="{80, 53, 443, 2290}" #要開放的TCP ports
udp_ports="{53, 514, 67, 68, 2290}" #要開放的UDP ports
#===========table===============
table <bruteforcers> persist #要阻擋的ip,寫在table裡面
# persist 代表kernel不會清除table裡的資料
#===========option===============
set skip on lo0 #skip loopback
#======traffic normalization=====
scrub in all #重新組合fragments,丟棄不明確意義的封包
#===========queueing=============#=======translation==============
nat on $ext_if from $lan_net -> ($ext_if) #轉址,只要來自內網ip皆轉成實體
rdr on $ext_if proto tcp from any to any port 2290 -> 192.168.1.203 port 2290
#轉送port x.x.x.x:2290=>192.168.1.203:2290
#============packet filter==========
#===========inbound=================
block quick from <bruteforcers> #阻擋黑名單
#pass in tcp {80,53,443,2290}
pass in quick on $ext_if proto tcp from any to any port $tcp_ports keep state
#keep state 若規則有keep state時,第一個符合規則的封包會在傳送與接收端建立一個狀態,傳送與接收端之間符合規則的封包就繞過檢驗
#pass in udp {53,67,68,2290}
pass in quick on $ext_if proto udp from any to any port $udp_ports
#pass in ssh
pass in quick inet proto tcp to $ext_if port ssh keep state(max-src-conn 5,max-src-conn-rate 20/60,overload <bruteforcers>flush global)
#max-src-conn 代表同一台主機可進行最大tcp三向交握次數
#max-src-conn-rate 代表指定時間內連結次數(60秒內20次連線)
#overload <bruteforcers> 若超過上述狀態,把ip記錄在table
#flush global 代表會清除所有狀態(狀態歸零)
#pass in icmp
pass in quick on $ext_if proto icmp all
block in log all #阻擋全部,並log#===========outbound===============
pass out all keep state #讓內到外的封包全部通過
########parameter#########
#pass通過
#block阻擋
#in 進來的流量
#out 出去的流量
#log 記錄在/var/log/pflog,並把封包送到pflog0的介面
#quick 若規則設置quick,封包符合此規則,就skip後續規則
#proto protocal的意思,ex.tcp,udp,icmp,icmp6
#from <source> port <source_port> to <dest> port <dest_port>
#all 代表from any to any

3. Reload rule and check parse in pf.conf file

# pfctl -nf /etc/pf.conf 
// -n Don't actually load rules, just parse them.
# pfctl -f /etc/pf.conf
// Reload the file.
# service pf start
// start pf.

Other command

# pfctl -sr
// Show pf filter rules.
# pfctl -sn
// Show NAT rules.
# pfctl -t table_name -Tshow
// show data in the table.

Read file pf.log

# tcpdump -n -tttt -r /var/log/pf.log
// -n Don't convert addresses to names.
// -tttt Print a timestamp, as hours, minutes, seconds, and fractions of a second since midnight, preceded by the date, on each dump line.
// -r Read packets from file.

Real-time display in pf interface

# tcpdump -n -tttt -i pflog0
// -i Listen on interface.
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade