動機
DockerやVM等でたくさんのOS環境(DebianかUbuntu)を何度も繰り返し構築してると、deb packageのダウンロードに時間かかってつらい。でもクライアントにproxyの設定をやろうとするとあちこちに設定を埋めたり、構築が終わったら逆に消したりしないといけなくなってそれはそれでつらい。
そうだ、透過プロキシを作ろう。
概要
透過プロキシサーバの構成にあたって、
- 既に稼働しているネットワークやルータの構成変更を最小限にしたい。
- 不具合があったら透過プロキシサーバを経由せずにHTTPアクセスできるようにしたい。
と思ったので、下記のようにすることにした。
- 透過プロキシサーバは、ルータとは独立して構成する。
- ルータからHTTPのパケットのみを、透過プロキシサーバとして構成したサーバに投げる。
透過プロキシサーバをブリッジ構成にしてルータの手前に挟むという手もあるが、そのためのハードウェアが余分に必要になる上に障害ポイントが増えるのが嫌なのでやめた。(キャッシュしたいだけだからね…)
設定
squid
Ubuntu 14.04 の squid-deb-proxy パッケージの設定をベースにした。
/etc/squid-deb-proxy/squid-deb-proxy.conf:
acl allowed_networks src "/etc/squid-deb-proxy/autogenerated/allowed-networks-src.acl"
# acl to_archive_mirrors dstdomain "/etc/squid-deb-proxy/autogenerated/mirror-dstdomain.acl"
acl blockedpkgs urlpath_regex "/etc/squid-deb-proxy/autogenerated/pkg-blacklist-regexp.acl"
# 透過プロキシに使うポートは intercept を付ける (transparentはobsolateだってさ)
http_port 8000 intercept
# interceptが無い通常のポートも空けておかないと起動時に警告出てうざい
http_port 8001
visible_hostname squid-deb-proxy
maximum_object_size 512 MB
cache_mem 2000 MB
maximum_object_size_in_memory 10240 KB
# cache_dir max 30GB
cache_dir aufs /var/cache/squid-deb-proxy 30000 16 256
cache_replacement_policy lru
cache_access_log /var/log/squid-deb-proxy/access.log
cache_log /var/log/squid-deb-proxy/cache.log
cache_store_log /var/log/squid-deb-proxy/store.log
pid_filename /var/run/squid-deb-proxy.pid
# refresh pattern for debs and udebs
refresh_pattern deb$ 129600 100% 129600
refresh_pattern udeb$ 129600 100% 129600
refresh_pattern tar.gz$ 129600 100% 129600
refresh_pattern gem$ 129600 100% 129600
# always refresh Packages and Release files
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
# handle meta-release and changelogs.ubuntu.com special
# (fine to have this on debian too)
refresh_pattern changelogs.ubuntu.com/* 0 1% 1
# only allow connects to ports for http, https
acl Safe_ports port 80
acl Safe_ports port 443 563
# only allow ports we trust
http_access deny !Safe_ports
# do not allow to download from the pkg blacklist
http_access deny blockedpkgs
# allow access only to official archive mirrors
# uncomment the third and fouth line to permit any unlisted domain
# http_access deny !to_archive_mirrors
# http_access allow !to_archive_mirrors
# don't cache domains not listed in the mirrors file
# uncomment the third and fourth line to cache any unlisted domains
# cache deny !to_archive_mirrors
# cache allow to_archive_mirrors
# cache allow all
# allow access from our network and localhost
http_access allow allowed_networks
# And finally deny all other access to this proxy
http_access deny all
# 「proxy使ってます」アピールしなくていいと思うのでヘッダ消しておく
forwarded_for off
request_header_access X-FORWARDED-FOR deny all
request_header_access Via deny all
request_header_access Cache-Control deny all
iptables
Ubuntuの iptables-persistent packageを使ってるが、要は -A PREROUTING
の2行が実行されればOK。
TCP destination 80 のパケットが飛んできたら 127.0.0.1:8000
(squidのポート)に投げ込む。
# Generated by iptables-save v1.4.21 on Wed Jan 20 17:23:36 2016
*nat
:PREROUTING ACCEPT [43:2457]
:INPUT ACCEPT [752:39853]
:OUTPUT ACCEPT [656:39391]
:POSTROUTING ACCEPT [656:39391]
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8000
-A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:8000
COMMIT
# Completed on Wed Jan 20 17:23:36 2016
ルータ
こちらではYAMAHA RTX1210 を使用しているので、それの設定。TCP 80だけを透過プロキシサーバに向かって投げるようにroutingをアレする。参考: フィルタ型ルーティング(ヤマハのドキュメント)
198.51.100.2
が透過プロキシサーバのIPアドレスだとするとこんな感じ。
ip route default gateway pp 1 gateway 198.51.100.2 filter 123456
ip filter 123456 pass 198.51.100.1,198.51.100.3-192.51.100.254 * tcp * www
# ↑198.51.100.2のdefault gatewayもこのルータだから198.51.100.2を除外しないとループするで。
ip filter set lan_common in 123456
ip lan1 secure filter name lan_common
ヤマハ以外のルータの場合はどうするのかわからんけど、業務用ルータならできると思う。
あとがき
キャッシュヒットすればGbEの速度でpackageが落ちてくるのでわりとおすすめ。