squid設定-デュアルホームドFW機(NIC3枚)で2つのLANセグメントにサービス提供

Debianパッケージに収録されているので、dselectでインストール。

デュアルホームドファイアウォールマシン上(NIC3枚)で稼動とし、LAN側のクライアントにWebプロキシサービス提供とする。
外側IP:192.168.1.11
LAN側IP:192.168.10.11、192.168.30.11
プロキシポート:3128

ドメイン名:mydomain.net

ドメイン名 ネットワークアドレス
wan側 wan.mydomain.net 192.168.1.0/24
LAN側その1 lan1.mydomain.net 192.168.10.0/24
LAN側その2 lan2.mydomain.net 192.168.30.0/24


/etc/squid/squid.conf の修正点。

http_port 192.168.10.11:3128 192.168.30.11:3128 プロキシ利用クライアント待ち受けアドレス:ポート指定。デュアルホームドマシンの場合等はアドレスも明示指定した方が良い。
icp_port 0 ICPポートは使わないので0指定。近隣プロキシと協調動作するときに指定する。
htcp_port 0 マルチキャストICPは受信しないので0指定。これは近隣プロキシと協調動作するときに指定する。
hierarchy_stoplist cgi-bin ?
hierarchy_stoplist 192.168.1.1
hierarchy_stoplist 192.168.
hierarchy_stoplist .lan1.mydomain.net
hierarchy_stoplist .wan.mydomain.net
hierarchy_stoplist .lan2.mydomain.net
URLにここで指定した文字列がある場合、そのサーバに直接アクセスして取ってくる、近隣プロキシには問い合わせない。今回近隣プロキシは利用しないが念の為指定を残しておく。
acl QUERY urlpath_regex cgi-bin \? 192.168.1.1 192.168. mydomain.net
no_cache deny QUERY
プロキシキャッシュの対象から除外する設定。ここではacl句のQUERYに定義された文字列のどれかがURL中に現れた場合次行のno_cache句のdeny指定によりそのサイトはキャッシュされない。
cache_mem 16 MB Squidの使用メモリ制限の目安を指定する。(転送中/最新/キャッシュされないオブジェクトが対象)。Squidは内部では4KBブロック単位でメモリを確保する。※注意:「16MB」だと起動時に警告がでる。正しくは「16 MB」で間にスペースを入れること。
cache_swap_low 90
cache_swap_high 95
ディスクキャッシュ使用量がcache_swap_low値を超え始めるとcache_swap_low値付近を維持しようとし始めます(古いものと新しいものの置き換えにより)。cache_swap_high値を超え始めるとよりcache_swap_high値付近を維持しようとディスクキャッシュオブジェクトを廃棄し始めます。
maximum_object_size 32768 KB ディスクキャッシュするオブジェクトの上限サイズ指定。これ以上大きいオブジェクトはディスクキャッシュされない。値を大きくすると回線帯域の節約に、小さくすると動作の高速性が上がる傾向になるようだ。(大きくとればHDDに記録する時間もかかるということか?)
# minimum_object_size 0 KB ディスクキャッシュするオブジェクトの下限サイズ指定。これ以下のオブジェクトはディスクキャッシュされない。今回はデフォルトの0を使うのでコメントアウトのまま。あまりに小さい(数十〜百バイト)のオブジェクトが多い場合Squidは4kbブロックでキャッシュするようなのでHDDのクラスタギャップによる無駄がでるかもしれない。余程HDD空間を節約したい場合以外は0の方が利便性は高いのではないかと思われる。
# maximum_object_size_in_memory 8 KB メモリキャッシュするオブジェクトの上限サイズ指定。これ以上大きいオブジェクトはメモリキャッシュされない。平均的に良く存在するサイズより大きく、ただしメモリを圧迫しないくらいのサイズにするべきらしい。ここではデフォルトのままでコメントアウト。
cache_dir ufs /var/spool/squid 540 16 256 ディスクキャッシュ容量指定。squidキャッシュ専用にHDDをマウントしてるなら総HDD容量からおよそ20%を引いた値以下にする(最大で指定してはならない。他にも付帯ファイルが生成される為)。可能であればSquidキャッシュ専用にパーティションを確保&マウントしそこを指定した方が良い。
aufs等の指定はマルチスレッドによりディスクI/Oにブロックされなくなるので性能が上がるように思えるがそれだけのマシン性能/リソースがないと高負荷時にはクライアント全般的に重くなるのではないかと推察する。余程の規模で運用しない限りufsで充分かもしれない。
cache_access_log /var/log/squid/access.log アクセスログの記録先指定。
cache_log /var/log/squid/cache.log キャッシュログの記録先指定。
cache_store_log /var/log/squid/store.log キャッシュの取捨、生存などについてのログの指定。無効にするには none 指定だが今回は有効にしておくい。解析ツールを書けばキャッシュ効率などがわかりそうだが・・・。
mime_table /usr/share/squid/mime.conf mimeテーブル。デフォルトの物でいいかも。
# useragent_log
ユーザーエージェントのログ記録先。逆プロキシならクライアント使用ブラウザの統計等がとれそうだが今回は内向きなのでデフォルトのnoneを使うのでコメントアウトのまま。
# referer_log リンク元のログ記録先。これも前項同様逆プロキシでサイト運営していれば有用かもしれないが、今回はデフォルトnoneを使うのでコメントアウトのまま。
pid_filename /var/run/squid.pid squidプロセスのPID記録先。これがないと起動管理が面倒になるのできちんと指定しておく。
client_netmask 255.255.255.255 ログファイルとcachemgrの記録でクライアントアドレスにマスクをかける。255.255.255.255にするとIPがそのまま記録されるためにどのクライアントがどのキャッシュを使ったかがログからわかるようだ。クライアントのプライバシーを守る為には255.255.255.0などとしてキャッシュからクライアントIPがはっきりわからないようにする事ができる。ここでは気にしないので255.255.255.255のままとする。
ftp_passive on Squidがファイアウォールの為にパッシブ接続を利用できない場合はonにするらしい。
# ftp_sanitycheck on FTPプロトコルは仕様上コントロールchとデータchが別サーバアドレスで行える(FTP転送リクエスト元アドレスとデータ転送指定先サーバアドレスを別にできる)。onにするとそれを許さない。一般的には異なることは稀なので偽装などを防止する為にはonにしておく方が良さそうである。デフォルトonなのでコメントアウトのまま。
dns_nameservers 192.168.10.11 通常は/etc/resolv.confを参照しているようだが、別途squidに特定のDNSサーバを利用させたい場合はここで指定する。今回は明示的にここで指定している。
redirect_rewrites_host_header on リダイレクト時にSquidがhost:ヘッダを上書きするかどうか。通常はonでいいと思われるが、アクセラレータモード等の場合はhttpサーバに対してSquid自身のホストをヘッダに上書きしてしまうらしいのでoffが好ましいのかもしれない。
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern . 0 20% 4320
通常サイトにはキャッシュ生存有効期限が明記されているはずだが、その期限の指定が無いオブジェクトなどにおいてのキャッシュ生存有効期限をここで指定できる。
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl to_localhost dst 127.0.0.0/8
acl SSL_ports port 443 563 444 # https, snews
#acl SSL_ports port 873 # rsync
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 563 # https, snews
acl Safe_ports port 444 # https
acl Safe_ports port 70 # gopher
#acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
#acl Safe_ports port 280 # http-mgmt
#acl Safe_ports port 488 # gss-http
#acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
#acl Safe_ports port 631 # cups
#acl Safe_ports port 873 # rsync
#acl Safe_ports port 901 # SWAT
acl purge method PURGE
acl CONNECT method CONNECT

http_access allow manager localhost
http_access deny manager
http_access allow purge localhost
http_access deny purge
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access deny to_localhost
ほぼデフォルト指定。場合によってはSSLポート等を追加するくらいでいいと思う。
acl clients_lan1 src 192.168.10.0/24
acl clients_lan2 src 192.168.30.0/24
http_access allow clients_lan1
http_access allow clients_lan2
http_access deny all
クライアントの許可設定。最後は全てを禁止でしめておくと安全。
icp_access deny all 近隣キャッシュからの全てのICP要求を無視する。今回は協調動作をさせないのでdenyとしている。
ident_lookup_access deny all ident検索はしない
cache_effective_user proxy
cache_effective_group proxy
squidの実行ユーザ/グループを指定する。これに合わせてキャッシュ/設定ファイル/ログディレクトリのユーザ:グループパーミッションを合わせておく。
debianだとデフォルトでproxyユーザ/グループが生成されているのでこれをそのまま使用。
visible_hostname unknown ホストネームをそのまま外部に公開せず、「unknown」として公開する。
logfile_rotate 7 ログローテーションで最大何個のバックアップを持つかの指定。
forwarded_for off クライアントのローカルIPアドレスをHTTPリクエストに付加させない。
log_icp_queries off 隣接キャッシュとの協調動作はさせないのでICPログはとらない。

※Squidを別途ソースから再コンパイルした場合ログローテイト設定ファイルで、
/etc/logrotate.d/squid 内の
/usr/sbin/squid -k rotate 行を
/usr/local/squid/bin/squid -k rotate などに変更した方がいい。

キャッシュディレクトリのパーミッション変更

# chown root:proxy /var/spool/squid
# chmod 775 /var/spool/squid
# chmod 770 /var/spool/squid

# /etc/init.d/squid start
※初回は自動的にキャッシュディレクトリを生成する。
 これはdebianパッケージ付属のスクリプト/etc/init.d/squid内で
 自動判別してるのでその他のディストリビューションでは初回のみ
 手動で squid -z 等として生成しなければならない。

○考察諸々

■ aclとhttp_access句について

以下だと192.168.10.0/24、192.168.30.0/24のアクセスは許可されるが、

acl clients_lan1 src 192.168.10.0/24
acl clients_lan2 src 192.168.30.0/24
http_access allow clients_lan1
http_access allow clients_lan2

http_access deny all

以下だと192.168.10.0/24、192.168.30.0/24のアクセスは許可されない。

acl clients_lan1 src 192.168.10.0/24
acl clients_lan2 src 192.168.30.0/24
http_access allow clients_lan1 clients_lan2
http_access deny all

これは192.168.10.0/24、192.168.30.0/24のアクセスは許可される。

acl clients src 192.168.10.0/24 192.168.30.0/24
http_access allow clients
http_access deny all

これはひょっとするとバグ?かもしれないが、複数行で定義されたacl〜src句をhttp_access句1行で指定できないようである。
しかし以下はうまく動作しているようである。

acl clients_lan1 src 192.168.10.0/24
acl clients_lan2 src 192.168.30.0/24
http_access deny !clients_lan1 !clients_lan2

見方によっては、deny指定はゆるいが、allow行は厳しい・・・とも見れるがこの規則性はちょっとわかりにくいし明記してる文書が身近では見あたらないが既知のことなのだろうか?。
この問題が長らくわからず6〜7年放置していたが今回ふと思い立って動作検証をしてすっきりしたw。
(ちなみに記憶によると少なくともsquid2.2stable4〜2.5.STABLE9 まで同じ動作なはず。)

■ 透過プロキシ

これはクライアントマシンのプロキシ設定の煩わしさを排除できるのがメリットで利用価値は高いと思われる。
ではデメリットはというとWebサイトアクセスで使用するポートは80だけではないということが上げられる。つまり透過プロキシは途中でそのポートを横取してSquidに投げ込む(リダイレクト)ことで実現されるが、その際の横取ポートが80だけではないということ。よってリダイレクトでは考えうるポート番号を全て(httpsポートやよくある8080ポート等)対応しなければならなくなる。使用されるポートは概ね決まっているが変わったポートに飛ばされるサイトなどでは閲覧できなくなる場合が稀に発生することが想定される。
あとは何か悪意のあるウィルス等にLAN内のクライアントマシンが感染している場合やスパイウェアの類により勝手にポート80をアクセスされた場合も透過処理により外部にパケットは流出する。そうなると別なセグメント/インターネット上の帯域を食うし他のマシンに迷惑をかける恐れもある。プロキシ認証をする手もあるが利用者の利便性を考えると本末転倒になるかもしれない。
そういう意味では透過プロキシは使用しない方がセキュアとも言えるかもしれない。

透過プロキシ程とはいかないが、一般ユーザの利便性を軽減する方法としてはブラウザに自動的にプロキシ設定を行う方法がある。これにはどこかに設定用のJavaスクリプトを設置できるWebサーバが必要になるらしい。LAN専用Webサーバが既に設置されている場合はこの手も有効かもしれない。


Wrote 2005.11.24