11月 22

FreeBSD+mpd+pfで快適なFlet’s PPPoEマルチセッションルーター生活

Tag: FreeBSDTOSHI @ 18:32:56

今更気づいたんだけどmpdって全然mssの問題解決してないのね…set iface enable tcpmssfixとかやっても全然効いてねーの。mss問題解決しなくて一番困るのがWindowsUpdateに繋げない事なのでまた厄介(;´Д`)
なんでぐぐって見つかるmpd使いはipfilter+ipnatばかりなのだろうかと想ったら、ipfilterでmssclampとかいう設定があるからなのね。一瞬私もそうしようかと想ったんだけど、某BBS某スレではpfマンセーみたいな雰囲気が流れてて

pfはkernel内でうごいてNATもしてmssな値の調整もできてライセンスもOkだしaltqとの連携もありでシンタックスも素敵。
これからはpfだとおもったり。

素敵じゃないですか!折角5-STABLEマシンだし、最先端技術でカコイイマシンを目指してみようということで、ipfw+natdとさようならすべく設定にいそしむ。

やはりまだトライしてる人が少ないのかあんまりぐぐっても情報が無い中、portsの頃から使用してる方を発見。おおいに参考にさせていただきました、感謝。でも、基本は5.3-R以降のマシンと、man pfctl & man pf.conf

5.3-Rマシンはどうかしらないけど、手元の5-STABLEマシンでは /etc/rc.d/pf をみるとこの中でpf.koを読んでくれてるので、kernelに必要なconfigはALTQのみ(無くても動くけど毎回怒られるので五月蝿くて嫌になる)。ということで、

options ALTQ

だけ入れてkernel作り直し。私はついでにipfw周りのconfigをはずす。やっておかないと、無駄にipfwが効いてdeny anyとかになってはまることに(←やったのかよ

次はpfのrules作り。デフォルトの /etc/pf.conf には触らず、 /etc/pf.rules というファイルに書く。/usr/share/examples/pf/faq-example1 の内容を基本に、上美谷さんのものも参考にゴリゴリっと。

# macros
int_if = "rl0"
ext_if = "ng0"
flets_if = "ng1"

tcp_services = "{ ssh, http }"
icmp_types = "{echoreq, unreach, squench, timex}"

priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"

# options
set block-policy return
set loginterface $ext_if

# scrub
scrub in all
scrub out all random-id max-mss 1414

# nat/rdr
nat on $ext_if from $int_if:network to any -> ($ext_if)
nat on $flets_if from $int_if:network to any -> ($flets_if)

# filter rules
block log all

pass quick on lo0 all

block drop in  quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets

# TCP outer to inner
pass in quick on $ext_if proto tcp from any to ($ext_if) \
   port $tcp_services flags S/SA keep state

# ICMP
pass in inet proto icmp all icmp-type $icmp_types keep state

# keep state
pass in  on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state

pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state

# keep state (Flet's)
pass out on $flets_if proto tcp all modulate state flags S/SA
pass out on $flets_if proto { udp, icmp } all keep state

# IPv6
pass on gif0 all
pass proto { 41, 58 } all

exampleのやつにFlet’sスクウェア向けのnatをつけて、mssを調整して、外部インターネットからsshとhttpを通すようにしただけ(ほんとはもっと書いてるんだけど、わざわざ穴教えるようなことはしない(笑))。なんでIPv6スルーしてるかというと、pfのv6のサンプルとか無くてまんどくなって、ip6fwでやらせてるからorz

rulesが出来たら、rc.confに仕込んで有効にしますよっと。ついでにログ鳥にpflogdも起動。

# pf
pf_enable="YES"
pf_rules="/etc/pf.rules"
pflog_enable="YES"

/var/log/pflog にtcpdump形式のバイナリがでてくるので、そいつを見て必要に応じてrulesを書き加えるなりして完成。ちゃんと読むもの読めば、意外にできるもんです。

ipfwは既にkernelからはずしてて、natdも捨てられるようになったので、mpdのup-scriptも上美谷さんに習って書き換え。とはいっても、rc.dのスクリプトを動かすだけだけど。

#!/bin/sh

/etc/rc.d/pf stop > /dev/null 2>&1
/etc/rc.d/pf reload > /dev/null 2>&1
/etc/rc.d/pf start > /dev/null 2>&1

さらに追記。私としてはもはや生活の一部となっているIRCのお話。この手のフィルタには必ずといってもいいくらい付きまとうDCCは、やはり問題が。これだけはlibalias使うipfw+natdの優れている点といえるのかなぁ。仕方ないので、市販ルーターよろしく、DCC SENDするクライアントのhost/portを決め打ちしてrdrして後ろ向き解決

# DCC host and port
dcc_host = "xxx.xxx.xxx.xxx"
dcc_port = "yyyy"

# rdr (for DCC)
rdr on $ext_if proto tcp from any to ($ext_if) port $dcc_port -> $dcc_host port $dcc_port

# TCP outer to inner (for DCC)
pass in quick on $ext_if proto tcp from any to $dcc_host \
   port $dcc_port keep state

コメントをどうぞ