【CentOS】Squid4でWebプロキシサーバを構築

企業内やデータセンタのLAN機器がインターネット上のWebサイトとHTTP/HTTPS通信を行う場合、Webプロキシサーバを介してインターネットと通信するのが一般的です。
CentOS 8の公式リポジトリから導入できる最新バージョンのSquid4を使用して、LAN機器とインターネット上のHTTP/HTTPS通信を仲介するWebプロキシサーバを構築してみます。

前提条件

以下の前提条件で検証しています。

  • ハードウェア: VirtualBox上の仮想マシン
  • OS: CentOS 8.0
  • プロキシソフトウェア: Squid4.4
  • 構築対象サーバはインターネットと疎通が取れること
  • 構築対象サーバは、インターネット上の公開ドメインの名前解決ができること
  • 各手順はroot権限を持つユーザで実施

OSは、CentOSインストールDVDのISOファイルから「最小限のインストール」を選択しインストールを行いました。
バージョン情報は以下の通りです。

# cat /etc/redhat-release
CentOS Linux release 8.0.1905 (Core)

# uname -r
4.18.0-80.el8.x86_64

システム構成概要

今回構築するプロキシサーバは、以下のようなシステム構成を想定しています。

パッケージのインストール

以下のコマンドを実行し、SquidのRPMパッケージをインストールします。

# yum -y install squid

以下のコマンドを実行し、Squidのバージョンが表示されることを確認します。

# squid -v
Squid Cache: Version 4.4
Service Name: squid
(略)

設定の変更

viなどのテキストエディタで、Squidの設定ファイルを開きます。

# vi /etc/squid/squid.conf

変更内容は以下の通りです。設定ファイルから該当箇所を検索して編集してください。
なお、インストール時の初期設定は、squid.conf.defaultという名前で設定ファイルと同じディレクトリに作成されるので、設定ファイルの事前バックアップは不要です。

# ACL localnetの変更
# デフォルトの通信許可ネットワークを削除して、自身の環境に合わせたネットワークアドレスを指定
# 以下の例では、 192.168.10.0/24 に所属するクライアントからのプロキシ通信を許可
acl localnet src 10.0.0.0/8     # RFC1918 possible internal network
acl localnet src 172.16.0.0/12  # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl localnet src fc00::/7       # RFC 4193 local private network range
acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machines
↓
acl localnet src 192.168.10.0/24

# ACL Safe_portsの変更
# デフォルトの通信許可プロトコルを削除して、通信を許可したいプロトコルを指定
# 以下の例では、 tcp/80(HTTP)とtcp/443(HTTPS)のプロキシ通信を許可
acl Safe_ports port 80      # http
acl Safe_ports port 21      # ftp
acl Safe_ports port 443     # 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 80
acl Safe_ports port 443


# リッスンポートを変更
# 以下の例では、企業ネットワークで一般的な8080を指定
http_port 3128
↓
http_port 8080


# キャッシュを有効化
# 書式は、cache_dir ufs <キャッシュ保存先ディレクトリ> <最大キャッシュサイズ> <第1階層のディレクトリ数> <第2階層のディレクトリ数>
# 以下の例では、保持するキャッシュのサイズを100MBから5000MBに増やしている
#cache_dir ufs /var/spool/squid 100 16 256
↓
cache_dir ufs /var/spool/squid 5000 16 256


### 以降はファイルの末尾に追記 ###

# アクセスログフォーマットと出力方法を変更
# 以下の例では、Squidプロセスから直接ファイルにログを出力させず、システムのsyslogソケットに出力させている
# ログ形式は、combinedを指定し、詳細情報を表示させている
access_log syslog:local0.info combined


# 各種セキュリティ対策
# プロキシアクセス元クライアントの情報を隠蔽する
visible_hostname unkown
forwarded_for off
request_header_access X-Forwarded-For deny all
request_header_access Via deny all
request_header_access Cache-Control deny all
request_header_access Referer deny all

ログ出力の設定

Squidのアクセスログは、他ソフトウェアのログファイルと運用を統一するために、local0のファシリティでsyslogに出力する設定としました。そのため、local0のログをファイルに出力するためのrsyslog用の設定ファイルを以下のコマンドで作成します。

# echo 'local0.* /var/log/squid/access.log' > /etc/rsyslog.d/squid.conf
# echo '& stop' >> /etc/rsyslog.d/squid.conf

以下のコマンドでrsyslogを再起動して設定を読み込みます。

# systemctl restart rsyslog

ログローテーションの設定

rsyslogがファイルに出力したアクセスログをローテーションさせるため、syslog用のログローテーション対象ファイルに、Squidアクセスログを追加します。

# sed -i '1i /var/log/squid/access.log' /etc/logrotate.d/syslog

インストール直後の設定では、/var/log/squid/配下のすべてのログがSquid用のログローテーション設定の対象に指定されています。アクセスログは前述のsyslog用のログローテーション設定対象に指定しているので、ローテーション処理が重複しないようにする必要があります。Squid用のログローテーション設定を変更し、同設定でローテーションする対象ログファイルを明示的に指定します。

# sed -i 's|/var/log/squid/\*\.log |cache.log\nsquid.out\nstore.log\n|' /etc/logrotate.d/squi

カーネルパラメータのチューニング

ある程度の規模の企業内LANクライアントから接続を受け付ける場合、OS初期設定のままだとSquidは性能限界を迎えてしまいます。必要に応じてカーネルパラメータをチューニングする必要があります。

コネクションテーブル(nf_conntrack)の拡張

1つ目のチューニングポイントとして、コネクションテーブル(nf_conntrack)の拡張を行います。
まずは現状のコネクション数と最大値を確認します。

# 現在のコネクション数
# cat /proc/sys/net/netfilter/nf_conntrack_count 
2

# コネクションテーブルの最大値
# cat /proc/sys/net/netfilter/nf_conntrack_max 
65536

nf_conntrackでは、1コネクションあたり300〜400バイト程度のメモリを消費します。サーバに搭載しているメモリ容量を考慮して値を決定する必要があります。
今回は、コネクションテーブルの最大値を65536 → 500000に変更します。最大値の変更は、以下のコマンドで実施します。

# echo 'net.netfilter.nf_conntrack_max = 500000' >> /etc/sysctl.conf
# sysctl -p
net.netfilter.nf_conntrack_max = 500000

ファイルディスクリプタ数の拡張

Squidは、キャッシュファイルやソケットファイルを大量に扱うため、OSのリソース制限でSquidプロセスがファイルにアクセスができなくなり、問題が発生することがあります。
ファイルディスクリプタ数の最大値を適宜修正し、大量のキャッシュファイルを扱えるようにします。

まずは現状のファイルディスクリプタの最大値を確認します。初期状態では、16384が最大値です。

# cat /proc/`ps -ef | grep '/usr/sbin/squid' | grep -v 'grep' | awk '{print $2}'`/limits | grep 'open'
Max open files            16384               16384               files 

ファイルディスクリプタの最大値は、以下の設定ファイルで指定されています。

# cat /usr/lib/systemd/system/squid.service | grep 'LimitNOFILE'
LimitNOFILE=16384

上記のsystemdユニットファイルは直接編集すべきでないので、パラメータ上書き用の設定ファイルを作成します。
本来は、運用中の監視情報を参考にチューニングを行うべきなのですが、今回は決め打ちで500000を指定します。

# mkdir /etc/systemd/system/squid.service.d
# echo '[Service]' > /etc/systemd/system/squid.service.d/limits.conf
# echo 'LimitNOFILE=500000' >> /etc/systemd/system/squid.service.d/limits.conf

systemdのユニットファイルをリロードし、Squidを再起動します。

# systemctl daemon-reload
# systemctl restart squid

再度ファイルディスクリプタの最大値を表示して、最大値が更新されていることを確認します。

# cat /proc/`ps -ef | grep '/usr/sbin/squid' | grep -v 'grep' | awk '{print $2}'`/limits | grep 'open'
Max open files            500000               500000               files  

ファイアウォールの許可設定

以下のコマンドを実行し、クライアントからのWebプロキシ通信をサーバのファイアウォールで許可します。

# firewall-cmd --add-port=8080/tcp --permanent
success

# firewall-cmd --reload
success

サービスの起動

以下のコマンドを実行し、サービスの自動起動有効化とサービス起動を行います。

# systemctl enable squid
Created symlink /etc/systemd/system/multi-user.target.wants/squid.service → /usr/lib/systemd/system/squid.service.

# systemctl start squid

以下のコマンドを実行し、サービスの起動状態を確認します。
Active:の項目がactive (running)になっていれば起動完了です。

# systemctl status squid
● squid.service - Squid caching proxy
   Loaded: loaded (/usr/lib/systemd/system/squid.service; enabled; vendor preset: disab>
   Active: active (running) since Thu 2019-10-10 12:25:58 JST; 28s ago
  Process: 11921 ExecStart=/usr/sbin/squid $SQUID_OPTS -f $SQUID_CONF (code=exited, sta>
  Process: 11914 ExecStartPre=/usr/libexec/squid/cache_swap.sh (code=exited, status=0/S>
 Main PID: 11922 (squid)
    Tasks: 3 (limit: 12371)
   Memory: 18.9M
   CGroup: /system.slice/squid.service
           ├─11922 /usr/sbin/squid -f /etc/squid/squid.conf
           ├─11924 (squid-1) --kid squid-1 -f /etc/squid/squid.conf
           └─11925 (unlinkd)
(略)

クライアント端末のプロキシ設定

Webプロキシクライアント側の設定例として、Windows(Firefox)とCentOSの例を記載します。

Windows(Firefox)

Firefox起動後、右上のメニューボタンから「オプション」を押下します。

「一般」タブの一番下にある「詳細設定」を押下します。

「手動でプロキシーを設定する」の欄に、WebプロキシサーバのIPアドレスとポート番号を入力します。
「すべてのプロトコルでこのプロキシーを使用する」にチェックを入れます。
「プロキシーなしで接続」の欄に、クライアント自身を示すホスト名やループバックアドレスを入力します。
上記を入力した後、「OK」を押下して設定を有効化します。

CentOS

以下の作業は、作業対象が明示されていない限りクライアント側のCentOSで実施します。
プロキシ設定を環境変数として読み込むための設定ファイルを作成します。
以下の例で192.168.10.1:8080を指定している部分は、自身の環境に合わせて変更します。

# cat << '__EOF__' > /etc/profile.d/proxy.sh
PROXY="192.168.10.1:8080" # プロキシサーバのIPアドレスとポート番号を指定
export http_proxy=$PROXY
export HTTP_PROXY=$PROXY
export https_proxy=$PROXY
export HTTPS_PROXY=$PROXY
export no_proxy="127.0.0.1,localhost" # プロキシ接続対象外を指定
export NO_PROXY="$no_proxy"
__EOF__

次回システムログイン時からは自動的に環境変数が読み込まれますが、作業中のシェルでは読み込まれないので手動で読み込みます。

# source /etc/profile.d/proxy.sh

Webプロキシの動作を確認するために、クライアント側で以下のコマンドを実行してHTTPリクエストを送信します。

# curl www.yahoo.co.jp

Webプロキシサーバで以下のコマンドを実行し、Squidのアクセスログが出力されていれば、Webプロキシ通信が行われています。

# cat /var/log/squid/access.log
Oct 10 12:46:18 localhost (squid-1)[11924]: 127.0.0.1 - - [10/Oct/2019:12:46:18 +0900] "GET http://www.yahoo.co.jp/ HTTP/1.1" 301 405 "-" "curl/7.61.1" TCP_MISS:HIER_DIRECT

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です