dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

MacにHomebrewでsquidをインストールし、Basic認証つきのプロキシサーバーを立てる

ローカルに検証用のプロキシサーバーを立てる方法を調べていて、Squid を使った方法を備忘録のためメモしておく。

Linux 向けの情報はよく出てくるけど、Mac 環境です。

インストール

Mac の場合、Homebrew 経由でインストールできる。

$ brew install squid

起動

ref. https://docs.brew.sh/Manpage#services-subcommand

$ brew services run squid

または

$ brew services start squid

を使う。

前者は一回きりの起動、後者は以後ログイン時に自動的に起動するようになる(はず。未確認)。

動作確認(Basic 認証なし)

この時点で一度動作を確認してみる。
デフォルトで、ポートは 3128 で起動するので、curl の場合

$ curl https://example.com -x http://localhost:3128

を試す。

起動していない、プロキシの URL が間違っているなどの場合は

curl: (7) Failed to connect to localhost port 3129: Connection refused

が返る。

設定ファイル(squid.conf)を確認する

Homebrew でインストールした場合、/usr/local/etc/squid.conf に設定ファイルが存在する。
ポート番号もここに書かれている。

#
# Recommended minimum configuration:
#

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 0.0.0.1-0.255.255.255    # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8       # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10        # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16   # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12        # RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16       # RFC 1918 local private network (LAN)
acl localnet src fc00::/7          # RFC 4193 local private network range
acl localnet src fe80::/10         # RFC 4291 link-local (directly plugged) machines

...

# Squid normally listens to port 3128
http_port 3128

...

Basic 認証を設定する

ここまでで Basic 認証なしのプロキシサーバーは構築できたので、ここに Basic 認証を設定していく。

htpasswd でユーザー名・パスワードの設定ファイルを生成する

squid の設定の前に、Basic 認証のユーザー名とパスワードを記録したファイルを用意する。
これには htpasswd というコマンドを使用する。

# コマンドを実行する場所は任意
$ htpasswd -c path/to/.htpasswd [ユーザー名]
New password:
Re-type new password:
Adding password for user [ユーザー名]

.htpasswd を生成する場所やファイル名はなんでもいい。

squid.conf に Basic 認証用の設定を追加する

先に結論から。
squid.conf の INSERT YOUR OWN RULE(S) ... の直後に以下を追加する。

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
auth_param basic program /usr/local/opt/squid/libexec/basic_ncsa_auth [先ほど生成した .htpasswd へのパス]
auth_param basic children 5 startup=5 idle=1
auth_param basic realm Squid proxy-caching web server
auth_param basic credentialsttl 2 hours
acl basic_ncsa proxy_auth REQUIRED
http_access allow basic_ncsa

参考

まず、一行目の

auth_param basic program /usr/local/opt/squid/libexec/basic_ncsa_auth [先ほど生成した .htpasswd へのパス]

については、

auth_param <認証方式> program <helper program> <引数>

Squid は Basic 認証以外にも複数の認証方式をサポートしているが、一行目はどれも同じ書き方で、↑のようなフォーマット。
helper program とは

http://www.squid-cache.org/Doc/man/

に一覧があるプログラムのいずれかを指定するよう。

今回のように htpasswd コマンドで生成したパスワードファイルを扱う場合は NCSA というのを使えばいいらしい。Homebrew でインストールした場合、これらは /usr/local/opt/squid/libexec/ にあるため、上のような指定になった。ググるbasic_ncsa_auth ではなく ncsa_auth を指定している例が見つかったが、この記事を書いたときの Squid のバージョン(4.11) では basic_ncsa_auth しか存在しなかった。

また、この program が引数にパスワードファイルを受け取るので、続けて先ほど生成した .htpasswd へのパスを記述する。

auth_param basic から始まる残りの数行はきちんと理解していない。
http://www.squid-cache.org/Versions/v4/cfgman/auth_param.html を読むとわかるかも。

動作確認(Basic 認証あり)

設定ができたので、Basic 認証ありバージョンを動作確認してみる。

$ brew services stop squid
$ brew services run squid

# または
$ brew services restart squid

Squid を再起動するのを忘れずに。

curl の場合

$ curl https://example.com -x http://[ユーザー名]:[パスワード]@localhost:3128

でレスポンスが返ってくれば成功。

認証に失敗すると

curl: (56) Received HTTP code 407 from proxy after CONNECT

が返る。

ブラウザで動作確認

システム設定 > ネットワーク > 詳細 > プロキシ

f:id:dackdive:20200430223624p:plain

1点ハマったポイントとして、自分の環境では Firefox は問題なかったが、Chrome だとこのプロキシ設定をうまく認識してくれないのか、ローディング中のまま画面が真っ白になった。

回避策としては、
Google Chromeでプロキシを使う方法(Chromeのみ・OS全体) - [開発環境 ツール類/プログラム全般] ぺんたん info
を参考に、Chrome--proxy-server オプションつきでコマンドラインから起動したところうまくいった。

$ cd /Applications/Google Chrome.app/Contents/MacOS
$ ./Google\ Chrome --proxy-server=localhost:3128

わからなかったこと

Basic 認証用の設定の最後の二行、

acl basic_ncsa proxy_auth REQUIRED
http_access allow basic_ncsa

なぜこれが必要なのかよくわからなかった。

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
http_access allow localnet
http_access allow localhost

で、ローカルネットワークからのアクセスが全部OKになっているので、

acl localhost proxy_auth REQUIRED

のようにするのかと思ったが、これだとうまくいかなかった。