zaki work log

作業ログやら生活ログやらなんやら

[Docker] コンテナでSquidを動かしてproxyサーバーを構築

2年近くproxyすらないネットに繋がらない環境にいて、少し前にようやくパブリッククラウドの自由ないんたーねっとを手に入れたぜうっひょーと思ったら、今度はついにproxy環境での検証をすることになったので、自宅ラボにも似たような構成作れないか、Squidproxyサーバーを立ててみました。

www.squid-cache.org

せっかくなのでDockerで。

完成予定図はこんな感じ。

f:id:zaki-hmkc:20200904224352p:plain

Squidを手作業で動かしてみる on Docker

なんとなくCentOS 7で、検証用コンテナを起動。
どうせ8080/TCP使うだろうから、publishもしておく。

[zaki@manager-dev squid]$ sudo docker run -p 8080:8080 -it centos:7 bash
[root@0e3f3daa90ba /]#

Squidインストール

[root@0e3f3daa90ba /]# yum install squid

:
:


Installed:
  squid.x86_64 7:3.5.20-15.el7_8.1

Dependency Installed:
  groff-base.x86_64 0:1.22.2-8.el7                         libecap.x86_64 0:1.0.0-1.el7
  libtool-ltdl.x86_64 0:2.4.2-22.el7_3                     perl.x86_64 4:5.16.3-295.el7
  perl-Carp.noarch 0:1.26-244.el7                          perl-Compress-Raw-Bzip2.x86_64 0:2.061-3.el7
  perl-Compress-Raw-Zlib.x86_64 1:2.061-4.el7              perl-DBI.x86_64 0:1.627-4.el7
  perl-Data-Dumper.x86_64 0:2.145-3.el7                    perl-Digest.noarch 0:1.17-245.el7
  perl-Digest-MD5.x86_64 0:2.52-3.el7                      perl-Encode.x86_64 0:2.51-7.el7
  perl-Exporter.noarch 0:5.68-3.el7                        perl-File-Path.noarch 0:2.09-2.el7
  perl-File-Temp.noarch 0:0.23.01-3.el7                    perl-Filter.x86_64 0:1.49-3.el7
  perl-Getopt-Long.noarch 0:2.40-3.el7                     perl-HTTP-Tiny.noarch 0:0.033-3.el7
  perl-IO-Compress.noarch 0:2.061-2.el7                    perl-Net-Daemon.noarch 0:0.48-5.el7
  perl-PathTools.x86_64 0:3.40-5.el7                       perl-PlRPC.noarch 0:0.2020-14.el7
  perl-Pod-Escapes.noarch 1:1.04-295.el7                   perl-Pod-Perldoc.noarch 0:3.20-4.el7
  perl-Pod-Simple.noarch 1:3.28-4.el7                      perl-Pod-Usage.noarch 0:1.63-3.el7
  perl-Scalar-List-Utils.x86_64 0:1.27-248.el7             perl-Socket.x86_64 0:2.010-5.el7
  perl-Storable.x86_64 0:2.45-3.el7                        perl-Text-ParseWords.noarch 0:3.29-4.el7
  perl-Time-HiRes.x86_64 4:1.9725-3.el7                    perl-Time-Local.noarch 0:1.2300-2.el7
  perl-constant.noarch 0:1.27-2.el7                        perl-libs.x86_64 4:5.16.3-295.el7
  perl-macros.x86_64 4:5.16.3-295.el7                      perl-parent.noarch 1:0.225-244.el7
  perl-podlators.noarch 0:2.5.1-3.el7                      perl-threads.x86_64 0:1.87-4.el7
  perl-threads-shared.x86_64 0:1.43-6.el7                  squid-migration-script.x86_64 7:3.5.20-15.el7_8.1

Complete!
[root@0e3f3daa90ba /]#

使い方を確認

[root@0e3f3daa90ba /]# squid --help
squid: invalid option -- '-'
Usage: squid [-cdhvzCFNRVYX] [-n name] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]
       -a port   Specify HTTP port number (default: 3128).
       -d level  Write debugging to stderr also.
       -f file   Use given config-file instead of
                 /etc/squid/squid.conf
       -h        Print help message.
       -k reconfigure|rotate|shutdown|restart|interrupt|kill|debug|check|parse
                 Parse configuration file, then send signal to
                 running copy (except -k parse) and exit.
       -n name   Specify service name to use for service operations
                 default is: squid.
       -s | -l facility
                 Enable logging to syslog.
       -u port   Specify ICP port number (default: 3130), disable with 0.
       -v        Print version.
       -z        Create missing swap directories and then exit.
       -C        Do not catch fatal signals.
       -D        OBSOLETE. Scheduled for removal.
       -F        Don't serve any requests until store is rebuilt.
       -N        No daemon mode.
       -R        Do not set REUSEADDR on port.
       -S        Double-check swap during rebuild.
       -X        Force full debugging.
       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.
[root@0e3f3daa90ba /]#

--helpじゃなくて-helpらしい。
まぁそれは置いておいて、設定は/etc/squid/squid.conf

# Squid normally listens to port 3128
http_port 3128

設定で「おや?」と思ったのはここ。
てっきり8080/TCPだと思ったけど、Squidのデフォルトは3128らしい。

Dockerの起動オプションで8080にしてしまったのでちょっと変更。

[root@0e3f3daa90ba /]# sed -ie 's/3128/8080/' /etc/squid/squid.conf

とりあえず起動してみる。

[root@0e3f3daa90ba /]# squid
squid[86]: Squid Parent: will start 1 kids
squid[86]: Squid Parent: (squid-1) process 88 started
[root@0e3f3daa90ba /]#

あら、バックグラウンドで起動するらしい

       -N        No daemon mode.

これかな。

[root@0e3f3daa90ba /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0  11828  1956 pts/0    Ss   12:07   0:00 bash
root         86  0.0  0.0  83808  3704 ?        Ss   12:19   0:00 squid
squid        88  0.1  4.1 670380 160864 ?       S    12:19   0:00 (squid-1)
squid        89  0.0  0.0  27440  1244 ?        S    12:19   0:00 (logfile-daemon) /var/log/squid/access.log
root         93  0.0  0.0  51756  1720 pts/0    R+   12:20   0:00 ps aux
[root@0e3f3daa90ba /]#
[root@0e3f3daa90ba /]#
[root@0e3f3daa90ba /]#
[root@0e3f3daa90ba /]# kill $(cat /var/run/squid.pid)

しばらく待つと停止する。

[root@0e3f3daa90ba /]# squid[86]: Squid Parent: (squid-1) process 88 exited with status 0

[root@0e3f3daa90ba /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0  11828  1964 pts/0    Ss   12:07   0:00 bash
root        100  0.0  0.0  51756  1708 pts/0    R+   12:22   0:00 ps aux

気を取り直して-N付与して、

[root@0e3f3daa90ba /]# squid -N

ホストOSで見ると以下の通り。

[zaki@manager-dev ~]$ ss -anptl | grep 8080
LISTEN     0      128       [::]:8080                  [::]:*
[zaki@manager-dev ~]$

ちなみにこの状態で8080にブラウザでアクセスするとこんな感じ。

f:id:zaki-hmkc:20200904230513p:plain

制限ネットワークからproxy設定してwebアクセス

[zaki@centos1 ~]$ curl www.google.com
curl: (7) Failed to connect to 2404:6800:4004:81e::2004: ネットワークに届きません
[zaki@centos1 ~]$ curl www.yahoo.co.jp
curl: (7) Failed connect to www.yahoo.co.jp:80; ホストへの経路がありません
[zaki@centos1 ~]$

この通り繋がらないネットワークになってる。

ここでproxy指定すると

[zaki@centos1 ~]$ curl -I https://www.yahoo.co.jp -x 172.29.0.11:8080
HTTP/1.1 200 Connection established

HTTP/1.1 200 OK
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Fri, 04 Sep 2020 12:31:05 GMT
Etag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
Set-Cookie: B=dgpradhfl4cs9&b=3&s=m0; expires=Mon, 05-Sep-2022 12:31:05 GMT; path=/; domain=.yahoo.co.jp
Vary: Accept-Encoding
X-Vcap-Request-Id: 892db93b-de68-434b-7b62-9414b8a950c5
X-Xss-Protection: 1; mode=block
Age: 0
Connection: keep-alive
Via: http/1.1 edge2503.img.umd.yahoo.co.jp (ApacheTrafficServer [c sSf ])
Server: ATS

[zaki@centos1 ~]$
[zaki@centos1 ~]$
[zaki@centos1 ~]$ curl -I https://www.google.com -x 172.29.0.11:8080
HTTP/1.1 200 Connection established

HTTP/1.1 200 OK
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Date: Fri, 04 Sep 2020 12:31:12 GMT
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Expires: Fri, 04 Sep 2020 12:31:12 GMT
Cache-Control: private

[...]

[zaki@centos1 ~]$

つながった。

Squidバージョン

[root@0e3f3daa90ba /]# squid -v
Squid Cache: Version 3.5.20
Service Name: squid
configure options:  '--build=x86_64-redhat-linux-gnu' '--host=x86_64-redhat-linux-gnu' '--program-prefix=' '--prefix=/usr' '--exec-prefix=/usr' '--bindir=/usr/bin' '--sbindir=/usr/sbin' '--sysconfdir=/etc' '--datadir=/usr/share' '--includedir=/usr/include' '--libdir=/usr/lib64' '--libexecdir=/usr/libexec' '--sharedstatedir=/var/lib' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--disable-strict-error-checking' '--exec_prefix=/usr' '--libexecdir=/usr/lib64/squid' '--localstatedir=/var' '--datadir=/usr/share/squid' '--sysconfdir=/etc/squid' '--with-logdir=$(localstatedir)/log/squid' '--with-pidfile=$(localstatedir)/run/squid.pid' '--disable-dependency-tracking' '--enable-eui' '--enable-follow-x-forwarded-for' '--enable-auth' '--enable-auth-basic=DB,LDAP,MSNT-multi-domain,NCSA,NIS,PAM,POP3,RADIUS,SASL,SMB,SMB_LM,getpwnam' '--enable-auth-ntlm=smb_lm,fake' '--enable-auth-digest=file,LDAP,eDirectory' '--enable-auth-negotiate=kerberos' '--enable-external-acl-helpers=file_userip,LDAP_group,time_quota,session,unix_group,wbinfo_group,kerberos_ldap_group' '--enable-cache-digests' '--enable-cachemgr-hostname=localhost' '--enable-delay-pools' '--enable-epoll' '--enable-ident-lookups' '--enable-linux-netfilter' '--enable-removal-policies=heap,lru' '--enable-snmp' '--enable-ssl-crtd' '--enable-storeio=aufs,diskd,rock,ufs' '--enable-wccpv2' '--enable-esi' '--enable-ecap' '--with-aio' '--with-default-user=squid' '--with-dl' '--with-openssl' '--with-pthreads' '--disable-arch-native' 'build_alias=x86_64-redhat-linux-gnu' 'host_alias=x86_64-redhat-linux-gnu' 'CFLAGS=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches   -m64 -mtune=generic -fpie' 'LDFLAGS=-Wl,-z,relro  -pie -Wl,-z,relro -Wl,-z,now' 'CXXFLAGS=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches   -m64 -mtune=generic -fpie' 'PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'

ビルドオプションが表示されている。

イメージ作成

Dockerfile

チューニングとかそういのは全て置いておいて、「動かす」という1点を目的としてこんな感じ。

FROM centos:7

RUN yum install -y squid; \
    sed -ie 's/3128/8080/' /etc/squid/squid.conf

CMD ["/usr/sbin/squid", "-N"]

build

squid:3.5.20-centos7というタグを設定してる。

[zaki@manager-dev 3.5.20-centos7]$ sudo docker build -t squid:3.5.20-centos7 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM centos:7
 ---> 7e6257c9f8d8
Step 2/3 : RUN yum install -y squid;     sed -ie 's/3128/8080/' /etc/squid/squid.conf
 ---> Running in e3e319e63db8
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * updates: ftp-srv2.kddilabs.jp

 [...]

Step 3/3 : CMD ["/usr/sbin/squid", "-N"]
 ---> Running in 63f1b7b50b0a
Removing intermediate container 63f1b7b50b0a
 ---> d7e39d9a875b
Successfully built d7e39d9a875b
Successfully tagged squid:3.5.20-centos7
[zaki@manager-dev 3.5.20-centos7]$
[zaki@manager-dev 3.5.20-centos7]$ sudo docker images squid
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
squid               3.5.20-centos7      d7e39d9a875b        28 seconds ago      345MB

できた。

run

[zaki@manager-dev 3.5.20-centos7]$ sudo docker run -d --rm -p 8080:8080 squid:3.5.20-centos7
bbd567a53fc6fdd50fce1a14873098f9e9e5db7327ec8d818ba32f2c433df2ed

この状態でリモートからproxy経由でHTTPアクセス。

[zaki@centos1 ~]$ curl -I https://www.google.com -x 172.29.0.11:8080
HTTP/1.1 200 Connection established

HTTP/1.1 200 OK
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Date: Fri, 04 Sep 2020 12:50:49 GMT
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Expires: Fri, 04 Sep 2020 12:50:49 GMT
Cache-Control: private

[...]

ちゃんと動いた。

Docker Hubから

キャッシュ消して最低限軽量化したイメージを公開しました。

hub.docker.com

次のコマンドで動きます。

$ sudo docker run -d --rm -p 8080:8080 zakihmkc/squid:3.5.20-centos7

ソースはこちら

github.com


Squidコンテナ停止中はこの通り。

[zaki@centos1 ~]$ curl -I https://www.google.com -x 172.29.0.11:8080
curl: (7) Failed connect to 172.29.0.11:8080; ホストへの経路がありません

関連ってわけじゃないけど、proxyじゃなくてルーティングするならこちら

zaki-hmkc.hatenablog.com


課題 (ログ)

stdoutへ書き込み不可

ログファイルのこと忘れてて、デフォルトのまま/var/log/squidに出力してる。
そして少し調べた感じだと、squidユーザーで動いている関係で、/dev/stdout(これは/proc/self/fd/1にリンクされている)への書き込みがうまくいかない。
また、動作を見る感じだと、squidプロセスが上がった後はログファイルは開きっぱなしなので、あとから/var/log/squid/access.logをsymlinkとかに差し替えても機能しない。

ボリュームでホストOSにマウントするか、ログ出力はオフにしてsyslog転送とかにしないとコンテナは難しいかな?

syslogは試してないけどhelpにこんなのがある。

       -s | -l facility
                 Enable logging to syslog.

syslog転送まわりはこちら

zaki-hmkc.hatenablog.com

Squidのログ設定周りはここ。
SquidFaq/SquidLogs - Squid Web Proxy Wiki

出力ファイルパスを変更する場合はsquid.confで

access_log /dev/stdout

とか書く(が、動作しなかった。/tmp/squid.logとかだと有効だけど)

回避策 (9/6追記)

コンテナ自体は(通常)rootで実行されるが、/usr/sbin/squidを実行するとSquidプロセスはsquidユーザーで動くため/dev/stdoutなどへ書き込み権限がないのがまずかった模様(きっちりとは調べてない)

で、単純にDockerfile内でchmodchownしても、ビルドコンテナの設定は実行時のコンテナに引き継がれないっぽいため、CMDで実行するコマンドをsquidでなく起動用スクリプトを用意し、その中で権限変更とSquidの起動を行うように変更。

これでstdoutへの書き込みがSquidプロセスからできるようになり、コンテナ内のログファイルをやめてdocker logsでログが見れるようにできた。

github.com

一応、chmodで動くのを確認してchownに変更してみたんだけど、OpenShiftみたいにコンテナ内の実行権限は非固定にする環境もあるし、どっちがいいんだろうなぁ。

おまけ (9/6追記)

Alpineベースのイメージも作りました。
イメージサイズが、277MBだったCentOS 7ベースから15.8MBまで小さくなってワロタ…

# docker run --name squid -d --rm -p 8080:8080 zakihmkc/squid

これで動くよ。

hub.docker.com