インストール
最近のFreeBSDには標準で組み込まれていますのでパッケージ等は不要です。
/etc/rc.conf で有効にします。(コマンドで自動的に編集してくれます)
# service pf enable # service pflog enable
access: 202835
最近のFreeBSDには標準で組み込まれていますのでパッケージ等は不要です。
/etc/rc.conf で有効にします。(コマンドで自動的に編集してくれます)
# service pf enable # service pflog enable
フィルタの設定を /etc/pf.conf に記載します。
# ------------------------------------------------------------------- # Macros: Interface assignments # ------------------------------------------------------------------- int_if = "{em0,wg0}" # Internal interfaces (LAN and WireGuard) nat_if = "ng0" # Interface for NAT operations ext_if = "ng0" # External-facing interface (WAN) lo_if = "lo0" # Loopback interface # ------------------------------------------------------------------- # Service port definitions # ------------------------------------------------------------------- tcp_services = "{ ssh, http, https, dhcpv6-client }" udp_services = "{ https, 51820 }" dhcpv6_ports = "{ dhcpv6-client, dhcpv6-server }" netbios_ports = "{ 135, 137, 138, 139, 445, 1433 }" icmp_in_types = "{ echoreq, unreach, squench, timex }" icmp_out_types = "{ echorep, unreach, squench, timex }" icmp6_types = "{ unreach, toobig, timex, paramprob, echoreq, echorep, neighbradv, neighbrsol, routeradv, routersol }" # ------------------------------------------------------------------- # Reserved and private address blocks (RFC1918, etc.) # ------------------------------------------------------------------- table <no_inet_addr> const { \ 127.0.0.0/8, 169.254.0.0/16, \ 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 \ } table <no_inet6_addr> const { fc00::/7, fe80::/10 } # ------------------------------------------------------------------- # Internal network segments # ------------------------------------------------------------------- table <in_net> { 10.0.0.0/16, 192.168.0.0/24 } # Local address # ------------------------------------------------------------------- # PF options # ------------------------------------------------------------------- set block-policy return # Return TCP RST or ICMP unreachable # ------------------------------------------------------------------- # Scrubbing: normalize packets # ------------------------------------------------------------------- scrub in all scrub out on $ext_if all random-id max-mss 1414 # ------------------------------------------------------------------- # NAT: outbound translations # ------------------------------------------------------------------- nat on $nat_if from <in_net> to ! <private> -> ($nat_if) # ------------------------------------------------------------------- # Filtering Rules # ------------------------------------------------------------------- # Load blacklistd anchor rules anchor "blacklistd/*" in on $ext_if # Default deny policy block log all pass quick on $lo_if all pass quick on $int_if from <in_net> to any # IPv6 internal traffic pass in quick on $int_if inet6 all pass out quick on $int_if inet6 all pass out quick on $ext_if inet6 all pass quick on $ext_if inet6 proto udp \ from fe80::/10 to fe80::/10 port $dhcpv6_ports # Block spoofed source addresses (reserved/private ranges) block drop in log quick on $ext_if from <no_inet_addr> to any block drop out log quick on $ext_if from any to <no_inet_addr> block drop in log quick on $ext_if inet6 from <no_inet6_addr> to any block drop out log quick on $ext_if inet6 from any to <no_inet6_addr> # Load modular block rules (e.g., countries, AP filters) anchor "block/*" in on $ext_if # Block IDENT queries block quick inet proto tcp from any to any port = ident # NetBIOS: block legacy SMB services traffic block log quick on $ext_if proto {tcp, udp} from any to any port $netbios_ports block log quick on $ext_if proto {tcp, udp} to any port $netbios_ports # ------------------------------------------------------------------- # Inbound service access (stateful) # ------------------------------------------------------------------- pass in quick on $ext_if inet proto tcp from any to any \ port $tcp_services flags S/SA modulate state pass in quick on $ext_if inet proto udp from any to any \ port $udp_services keep state pass in quick on $ext_if inet proto tcp from any to any \ port 49152 >< 65535 flags S/SA modulate state # ------------------------------------------------------------------- # Multicast handling (for protocols like OSPF) # ------------------------------------------------------------------- pass in quick from any to 224.0.0.0/8 allow-opts pass out quick from any to 224.0.0.0/8 allow-opts # ------------------------------------------------------------------- # ICMPv4 traffic # ------------------------------------------------------------------- pass in quick inet proto icmp all icmp-type $icmp_in_types keep state pass out quick inet proto icmp all icmp-type $icmp_out_types # ------------------------------------------------------------------- # Outbound IPv4 traffic # ------------------------------------------------------------------- pass out quick on $ext_if proto tcp all modulate state flags S/SA pass out quick on $ext_if proto {udp, icmp} all keep state # ------------------------------------------------------------------- # IPv6 traffic handling # ------------------------------------------------------------------- pass inet6 proto ipv6-frag keep state pass in quick inet6 proto icmp6 all \ icmp6-type $icmp6_types allow-opts keep state # Allow incoming IPv6 TCP services pass in quick on $ext_if inet6 proto tcp from any to any \ port $tcp_services flags S/SA modulate state pass in quick on $ext_if inet6 proto udp from any to any \ port $udp_services keep state # Allow high ephemeral ports for IPv6 pass in quick on $ext_if inet6 proto tcp from any to any \ port 49152 >< 65535 flags S/SA modulate state pass out quick on $ext_if inet6 proto {tcp,udp,icmp6} all keep state
blacklistdは標準でFreeBSDに組み込まれています。
/etc/rc.confに以下の行を追加します。
sshd_enable="YES" sshd_flags="-o UseBlacklist=yes" blacklistd_enable="YES" blacklistd_flags="-f"
必要なら、/etc/blacklistd.conf をポリシーに合うように編集します。
blacklistdを起動します。
# service blacklistd start
国別フィルタのディレクトリを生成します。
# mkdir -p /etc/pf.block # cd /etc/pf.block
/etc/pf.block/update_blocktable.sh を以下の内容で生成します。
https://www.ipdeny.com/ipblocks/data/countriesから国別のIPアドレスを取得して、リストを更新するスクリプトです。
#!/bin/sh PFCTL="/sbin/pfctl" ANCHOR_FILE="/etc/pf.block/countries.conf" ZONE_TMPDIR="/var/tmp/pf.zone.$$" COUNTRY_FILE="/etc/pf.block/countries" BASE_URL="https://www.ipdeny.com/ipblocks/data/countries" EXT_IF="ng0" TABLE_NAME="country_block" : > "$ANCHOR_FILE" echo "# Auto-generated PF anchor for $TABLE_NAME" >> "$ANCHOR_FILE" echo "" >> "$ANCHOR_FILE" echo "table <${TABLE_NAME}> const {" >> "$ANCHOR_FILE" [ -f "$COUNTRY_FILE" ] || { echo "Missing country file: $COUNTRY_FILE" >&2 exit 1 } mkdir -p "$ZONE_TMPDIR" while read CODE; do case "$CODE" in ""|\#*) continue ;; esac ISO_LOWER=$(echo "$CODE" | tr 'A-Z' 'a-z') ZONE_URL="${BASE_URL}/${ISO_LOWER}.zone" ZONE_FILE="${ZONE_TMPDIR}/${ISO_LOWER}.zone" if fetch -q -o "$ZONE_FILE" "$ZONE_URL"; then cat "$ZONE_FILE" >> "$ANCHOR_FILE" else logger "Zone missing or fetch failed: $CODE" fi done < "$COUNTRY_FILE" rm -rf "$ZONE_TMPDIR" echo "}" >> "$ANCHOR_FILE" echo "block in log quick on ${EXT_IF} from <${TABLE_NAME}> to any" >> "$ANCHOR_FILE" if ${PFCTL} -n -a block/countries -f "$ANCHOR_FILE"; then ${PFCTL} -a block/countries -f "$ANCHOR_FILE" logger "PF anchor reloaded: block/countries" else echo "Syntax error in anchor file. Reload skipped." >&2 exit 1 fi
実行権限を付与します。
# chmod +x /etc/pf.block/update_countory.sh
/etc/pf.block/countriesを以下の内容で生成します。
このファイルは、国コードを1行ずつ記載します。(cnは中国、kpは北朝鮮)
cn kp
/etc/pf.block/update_countory.sh を実行して、国別フィルタのファイルを生成します。
# /etc/pf.block/update_countory.shうまく動くようなら、/etc/pf.block/update_blocktable.sh を定期的に実行するように cron に設定します。
cronの設定例は以下の通りです。
# crontab -e
以下の行を追加します。(毎週日曜日の午後8時に更新します)
0 20 * * 0 /etc/pf.block/update_blocktable.sh >/dev/null 2>&1
# service pf start
pfがすでに有効になっている場合は、以下のコマンドで設定を読み込みます。
# pfctl -f /etc/pf.conf