DHCP
Firewall
NAT
Alternate queueing
Bonus-Authenticates client PCs with a captive portal
Hint
我是使用實驗室的 VMware Esxi 環境,我拿了三個 public IP,兩個配給 fw[1|2] em0,一個用在 em0 carp,這次作業重點會在兩台 firewall(ksh_firewall1、ksh_firewall2) 上面
先開三台 vSwitch,分別用於內網(NA2_ksh_inner)、外網、CARP & pfsync 專屬(NA2_ksh_pfsync)
接著開第一台 firewall(NA2_firewall1) 需要三張網卡,分別接在三台 vSwitch 上,接著把 OS 灌起來,因為之後要重編核心,所以記得要裝 src
安裝 DHCP Server
#pkg install isc-dhcp43-server
DHCP 設定檔
option domain-name "example.org";
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.101 192.168.1.200; #要發的 IP 範圍
option domain-name "ksh_fw.nctucs.net"; #domain name
option routers 192.168.1.253; #router, 因為在這次架構中,會幫忙內網 routing 的是兩台 fw,所以這個要設成兩台 fw 的內網 carp IP
option broadcast-address 192.168.1.255;
option domain-name-servers 140.113.17.5, 140.113.1.1;
default-lease-time 3600;
max-lease-time 21600;
}
#兩台web拿固定IP
host kshweb1 {
hardware ethernet 00:0c:29:66:71:d5; #拿固定 IP 機器的 mac-address
fixed-address 192.168.1.1; #固定 IP,記得跟上面動態分配的隔開
}
host kshweb2 {
hardware ethernet 00:0c:29:88:27:ad;
fixed-address 192.168.1.2;
}
開機啟動
# DHCP Setting dhcpd_enable="YES" dhcpd_flags="-q" dhcpd_conf="/usr/local/etc/dhcpd.conf" dhcpd_ifaces="em2" dhcpd_withumask="022" # file creation mask
接下來的firewall、NAT、ALTQ 都是靠 pf 做的
重編 kernel
確認 hardware platform
% uname -m
移動到目錄底下複製一份核心,名字任取,修改內容
cd /usr/src/sys/amd64/conf/ cp GENERIC kernel_pf
ident kernel_pf ... # Option and device for PF and PFSync device pf device pflog device pfsync # For Using PF ALTQ options ALTQ options ALTQ_CBQ # Class Bases Queuing (CBQ) options ALTQ_RED # Random Early Detection (RED) options ALTQ_RIO # RED In/Out options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC) options ALTQ_PRIQ # Priority Queuing (PRIQ) options ALTQ_NOPCC # Required for SMP build
重新編譯,安裝新 kernel
# cd /usr/src # make buildkernel KERNCONF=kernel_pf # make installkernel KERNCONF=kernel_pf
pf rule
#################################################################
# Macro definitions
#################################################################
ext_if="em0"
lan_net="192.168.1.0/24"
int_if="em2"
#################################################################
# Tables
#################################################################
table <ssh_bruteforce> persist
#table <trusted> { 140.113.83.0/24 }
#################################################################
# Options
#################################################################
set skip on lo0
#################################################################
# Normalization
#################################################################
scrub in all
#################################################################
# Queueing
#################################################################
altq on $ext_if cbq bandwidth 100Mb queue { main, ftp, udp, web, ssh, icmp }
queue main bandwidth 28% cbq(default borrow red)
queue udp bandwidth 30% cbq(borrow red)
queue web bandwidth 20% cbq(borrow red)
queue ssh bandwidth 20% cbq(borrow red) { ssh_interactive, ssh_bulk }
queue ssh_interactive priority 7 bandwidth 20%
queue ssh_bulk priority 5 bandwidth 80%
queue icmp bandwidth 2% cbq
#################################################################
# Translation
#################################################################
nat pass on $ext_if from $lan_net to any -> 140.113.24.184 #內網流量 nat 到對外網卡
no nat on $ext_if from !$lan_net to any #非內網 IP 不做 NAT
#內部兩台web server 做 round-robin ,同 IP 連線固定不跳換(sticky-address)
rdr on $ext_if proto tcp from any to any port 80 -> {192.168.1.1, 192.168.1.2} round-robin sticky-address
#內部client url 使用 public IP 連線到web server 要多做一次nat
rdr on $int_if proto tcp from $lan_net to $ext_if port 80 -> {192.168.1.1, 192.168.1.2} round-robin sticky-address
nat on $int_if proto tcp to {192.168.1.1, 192.168.1.2} port 80 -> $int_if
#################################################################
# Filtering
#################################################################
block drop in quick on $ext_if from <ssh_bruteforce> to any
pass in quick on $ext_if from <trusted> to any
#block in on $ext_if proto tcp from any to $ext_if port 22
pass quick on em1 proto pfsync keep state (no-sync)
pass in quick on $ext_if proto { tcp, udp } from any to $ext_if port {ssh, www} keep state
pass log quick on $ext_if proto tcp to port ssh queue (ssh_bulk, ssh_interactive)
pass in quick on $ext_if proto tcp to port www queue http
pass out on $ext_if proto udp queue udp
pass out on $ext_if proto icmp queue icmp
pass proto carp
pass quick on $ext_if proto {tcp, udp} from 140.113.24.187 keep state
#block in quick on $ext_if all
rc.conf
#package filter setting pf_enable="YES" pf_rules="/etc/pf.conf" pf_flags="" # pfctl 啟動時的附加選項 pflog_enable="YES" pflog_logfile="/var/log/pflog" pflog_flags="" pfsync_enable="YES" pfsync_syncdev="em1" gateway_enable="YES"
將 carp module 載入核心
carp_load=“YES”
# kldload carp
設定 alias IP
hostname="kshfw1.nctucs.net" ifconfig_em0="inet 140.113.24.187 netmask 255.255.255.224" ifconfig_em0_alias0="vhid 1 advskew 100 pass youpasswd 140.113.24.184/27" defaultrouter="140.113.24.161" ifconfig_em1="172.20.1.1 netmask 255.255.255.0" ifconfig_em2="inet 192.168.1.253 netmask 255.255.255.0" ifconfig_em2_alias0="vhid 2 advskew 100 pass youpasswd 192.168.1.252/32"
# /etc/rc.d/netif restart # /etc/rc.d/routing restart
設定 preempt
net.inet.carp.preempt=1
pf 放行 carp 封包
pass proto carp
# service pf reload
pfctl -s state 檢測兩邊 state 是否相同,確保連線狀態是有同步的