【AWS メモ⑦】リバースプロキシの設定(Squid3.5)

Squid3.5でリバースプロキシ設定を仕事で使う機会があったので備忘録的なものを残しておく。

## 前提

以下の環境で実行。



サブネット

| サブネット名   | ルートテーブル設定                        |
| -------------- | ----------------------------------------- |
| public-subnet  | ・local                                   |
| private-web-subnet | ・local<br />・インターネットゲートウェイ |



セキュリティグループ

| セキュリティグループ名 | 設定                                                         |
| ---------------------- | ------------------------------------------------------------ |
| public-sg              | ・社内グローバルIPアドレスからのアクセスを許可(ポート22)<br />・HTTPアクセスを許可(ポート80)|
| private-web-sg             | ・public-sgからのアクセスのみ許可(ポート80)                  |



EC2

| ホスト名       | OS             | セキュリティグループ |
| -------------- | -------------- | -------------------- |
| proxy-server   | Amazon Linux 2 | public-sg            |
| private-web-server | Amazon Linux 2 | private-sg           |



プライベートサブネット内のWebサーバへのアクセスはパブリックサブネットに構築したプロキシサーバを経由して行う。
![スクリーンショット 2019-10-20 6.35.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/231cf09f-b120-1931-1d45-973f9ab7e53c.png)


## プロキシサーバーの設定

proxy-server にSquid3.5をインストールする。

```console
$ sudo yum install squid -y
```



自動起動を有効にする。

```
$ sudo systemctl enable squid
```


Squidの設定ファイルを開く。

```console
$ sudo vi /etc/squid/squid.conf
```


設定ファイルに、以下の設定を追加する。
ここでは、 HTTPアクセスを全て許可する。

```console
http_access allow all
```

ポート番号の指定（デフォルトでは3128）箇所をコメントアウトする。
転送先の設定を追加する。

```console
# Squid normally listens to port 3128
#http_port 3128  ← コメントアウト

# 以下の形式で転送先の設定を追加
# http_port <SquidサーバのプライベートIPアドレス>:<ポート番号> accel defaultsite=<WebサーバのプライベートIPアドレス>
http_port xxx.xxx.xxx.xxx:80 accel defaultsite=xxx.xxx.xxx.xxx
```

キャッシュ設定を追加する。

```console
# WebサーバのプライベートIPアドレス を設定
cache_peer xxx.xxx.xx.xxx parent 80 0 no-query originserver

# メモリキャッシュサイズを設定
cache_mem 256 MB
```

最後に、ホスト名定義を追加する。

```console
# WebサーバのプライベートIPアドレス を設定
visible_hostname xxx.xxx.xxx.xxx
```


設定完了後、サービスを再起動する。

```console
$ sudo service squid restart
```

### 動作確認（Webサーバなし）

Webサーバを起動せずにSquidのサーバが正常に動作しているかを確認する。

ブラウザにプロキシサーバのIPアドレスを入力して、アクセスする。
以下の画面が表示されていればとりあえずアクセスは完了している。ただし、吹き出し箇所に`visible_hostname`に設定したIPアドレスが表示されてしまう。
![1000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/0c5b71cf-23f8-4704-16c9-829db06ea800.png)

なるべくブラウザ側からサーバの情報は確認できないようにした方が良いので、先ほどの設定を見直す。

Squidの設定ファイルを開く。

```console
$ sudo vi /etc/squid/squid.conf
```

こざかしいが`unknown`と表示されるように変更する。

```console
# WebサーバのプライベートIPアドレス を設定
visible_hostname unknown
```

設定完了後、サービスを再起動する。

```console
$ sudo service squid restart
```

今度は、`unknown`と表示されるようになる。
![1000-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/db440a8a-60bc-841c-85a6-57aa79b7ab1a.png)

次は、バージョンも非表示にする。

Squidの設定ファイルを開く。

```console
$ sudo vi /etc/squid/squid.conf
```

以下の設定を追加して、バージョンを非表示にする。

```console
httpd_suppress_version_string on
```

設定完了後、サービスを再起動する。

```console
$ sudo service squid restart
```

今度は、バージョンが表示されなくなる。
![1000-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/535aa8c3-f69f-1d17-39ed-ae38f1d370ad.png)

Squid側の設定は以上で終了。

## Webサーバ側の設定

今回は、Apacheサーバを起動してアクセスできることを確認するので、Apacheの起動だけ行う。

```console
$ sudo systemctl start httpd
```

## プロキシサーバ経由でWebサーバのアクセス

ブラウザにプロキシサーバのIPアドレスを入力して、アクセスする。
Apacheのテストページが表示されることを確認する。
![1000-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/a2838f7c-9ed8-f60a-4d8a-89e31f3146c5.png)


## おまけ：複数のWebサーバへ処理を割り振る場合の設定

例えば、WebサーバA~Cまである場合は以下のように設定を行う。
ラウンドロビンで負荷分散されるようになる。

```console
# http_port <SquidサーバのプライベートIPアドレス>:<ポート番号> accel defaultsite=<WebサーバAのプライベートIPアドレス>
http_port xxx.xxx.xxx.xxx:80 accel defaultsite=xxx.xxx.xxx.xxx

cache_peer <WebサーバAのプライベートIPアドレス> parent 80 0 no-query originserver round-robin
cache_peer <WebサーバBのプライベートIPアドレス> parent 80 0 no-query originserver round-robin
cache_peer <WebサーバCのプライベートIPアドレス> parent 80 0 no-query originserver round-robin
```

## 補足
AWSでリバースプロキシを使用する場合、ELBを使用することが多いが、ELBでは5分間隔でのログ取得となっている。
そのため、リアルタイムのログ監視を行いたい場合はプロキシサーバを自前で用意する場合がある。
もし構築する必要がある場合は、今回使用したようなEC2での運用だと単一障害点になるので、ECSを使用すると良いかもしれない。