サーバー構築：TerraformとSquidを活用したAWS基盤上のプロキシサーバーの構築とアクセスログ確認

## はじめに
今回は、AWSのクラウド基盤上に `Squid` というミドルウェアを使い、プロキシサーバーを構築していきます。

:::note info
**この検証では、主にネットワークの観点から技術的な学びを深めるとともに、自分自身の復習を兼ねて体系的にまとめています。**
:::

***この記事は個人レベルの検証内容に基づいています。*** そのため、内容が実運用環境に適さない場合があることをご了承ください。

***この内容が、どなたかの技術的な参考になれば幸いです。***

## 書こうと思ったきっかけ
普段、自宅のローカルエリアネットワーク内では `Squid` を使ってプロキシサーバーを構築しています。

:::note warn
***一部の端末は、このプロキシサーバーを経由してインターネットに接続するようネットワークを設定しています。***
:::

しかし、以前から「**AWSのパブリッククラウド上に自分専用のプロキシサーバーを構築したい**」と考えていました。時間が取れたので、この機会に実際に構築してみることにしました。

実は以前、一度挑戦した際に、Squidの設定ファイルの編集中にエラーが発生し、挫折した経験があります...。

:::note info
***しかし、今回はその問題を解決したため、改めて手順を整理し、備忘録として記事にまとめることにしました。***
:::

## プロキシサーバーについて

プロキシサーバーは、クライアントとインターネットの間に位置し、通信を中継するサーバーです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/34511ec7-bb53-8fe9-7fa3-412d469d4c53.png)
引用画像：https://www.gate02.ne.jp/media/it/column_107/

これにより、以下のような利点があります：

- **アクセス制御**：特定の端末やサイトへのアクセスを制限。
- **匿名性の確保**：クライアントのIPアドレスを隠蔽。
- **通信監視・ログ記録**：ネットワーク利用状況の可視化。
- **キャッシュ機能**：データの一時保存により通信速度を向上。

:::note info
**特に企業では、セキュリティの向上やネットワークトラフィックの最適化に広く活用されています。**
:::

なお、前回自宅に構築した際の手順は、過去の記事にまとめています。***興味のある方は、ぜひ参考にしてみてください！***

https://qiita.com/free-honda/items/27a201413787414b0108

## 今回使うコードについて

今回使用するコードは、シンプルなシングル構成で、検証目的に特化して作成しています。

:::note warn
**今回は、AWSの基本的なネットワーク構成からEC2インスタンスの構築までを、Terraformを使用して一括で構築します。**
:::


ただし、それ以降のOS内部の細かい設定やファイル編集などは手動で行います。***この手順については、後ほど詳しく説明します。***

また、`associate_public_ip_address = true` という設定を使用することで、インスタンスにパブリックIPアドレスが自動的に割り当てられるようにしています。

```main.tf
provider "aws" {
  region = "ap-northeast-1" # Tokyo region
}

# VPC作成
resource "aws_vpc" "main_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "terraform-main-vpc"
  }
}

# サブネット作成 (パブリックサブネット)
resource "aws_subnet" "public_subnet" {
  vpc_id                  = aws_vpc.main_vpc.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = true

  tags = {
    Name = "terraform-public-subnet"
  }
}

# インターネットゲートウェイ作成
resource "aws_internet_gateway" "main_igw" {
  vpc_id = aws_vpc.main_vpc.id

  tags = {
    Name = "terraform-main-igw"
  }
}

# ルートテーブル作成
resource "aws_route_table" "public_route_table" {
  vpc_id = aws_vpc.main_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main_igw.id
  }

  tags = {
    Name = "terraform-public-route-table"
  }
}

# サブネットとルートテーブルの関連付け
resource "aws_route_table_association" "public_association" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_route_table.id
}

# セキュリティグループ作成
resource "aws_security_group" "public_sg" {
  vpc_id = aws_vpc.main_vpc.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # HTTPアクセスを許可
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # SSHアクセスを許可
  }

  ingress {
    from_port   = 3128
    to_port     = 3128
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # カスタムTCP (ポート3128) を許可
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"] # すべてのアウトバウンドを許可
  }

  tags = {
    Name = "terraform-public-sg"
  }
}

# EC2インスタンス作成
resource "aws_instance" "proxy_ec2" {
  ami                         = "ami-08f52b2e87cebadd9" # Amazon Linux 2023 AMI (Tokyo region)
  instance_type               = "t2.micro"
  subnet_id                   = aws_subnet.public_subnet.id
  security_groups             = [aws_security_group.public_sg.id]
  associate_public_ip_address = true # パブリックIPv4アドレスを有効化

  depends_on = [aws_security_group.public_sg] # 修正: セキュリティグループに依存

  tags = {
    Name = "terraform-proxy-ec2"
  }
}
```

:::note warn
**※補足**
***セキュリティグループの設定で、ingressにカスタムTCPポート3128を追加することで、ポート3128のTCP通信がすべてのIPアドレスから許可されるようになります。***
:::

## OS内部の設定について

### Squidのインストール

EC2インスタンスには、[Instance Connect](https://qiita.com/free-honda/items/90fddc7b90246f4d3719)を使用して接続します。接続後、まずパッケージを更新します。

```bash
sudo dnf update -y
```

次に、Squidをインストールします。

```bash
sudo dnf install squid -y
```

### Squidの設定
まず、Squidの設定ファイルを編集します。

```bash
sudo vi /etc/squid/squid.conf
```

#### 外部ネットワークからのアクセスを許可する設定

デフォルトでは、Squidは `localhost` からのリクエストのみを許可しています。***そのため、外部クライアントからアクセスを許可するためには、`http_access` セクションに適切なルールを追加する必要があります。***


#### 変更箇所 1: 外部ネットワークアクセスを許可

**変更前**

デフォルト設定では、`http_access allow localnet` がコメントアウトされています。

```/etc/squid/squid.conf
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
# http_access allow localnet
```

**変更後**

`http_access allow localnet` を有効化し、コメントを外します。

```/etc/squid/squid.conf
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
http_access allow localnet
```

#### 変更箇所 2: グローバルIPアドレスを許可

**変更前**

現在のSquid設定では、接続元のグローバルIPアドレスを許可するACLが記載されていません。

```/etc/squid/squid.conf
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
# For example, to allow access from your local networks, you may uncomment the
# following rule (and/or add rules that match your definition of "local"):
http_access allow localnet
```

**変更後**

以下のように、特定のグローバルIPアドレスを許可するACLを追加します。

:::note warn
`acl allowed_ip src <グローバルIPアドレス>` で許可したいIPアドレスを指定し、`http_access allow allowed_ip` を記述します。
:::

このルールは、`http_access allow localnet` の前に配置してください。

```/etc/squid/squid.conf
# Allow access from a specific global IP address
acl allowed_ip src <グローバルIPアドレス>
http_access allow allowed_ip

# Allow access from local networks
http_access allow localnet
```

ご自身のクライアント端末のグローバルIPアドレスが分からない場合は、以下のサイトにアクセスすると確認できます。***ぜひお試しください！***

https://www.ugtop.com/spill.shtml

#### 変更箇所 3: 最後の`http_access deny all`ルール

**変更前**

最後にすべてのアクセスを拒否するルールがあります。この行の位置は変更不要ですが、新しい許可ルールはこの行の前に追加する必要があります。

```/etc/squid/squid.conf
http_access deny all
```

**変更後**

この行自体はそのままです。ただし、`http_access allow localnet` をこの行の上に記述します。

```/etc/squid/squid.conf
http_access allow localnet
http_access deny all
```

### 再起動して設定を反映
設定ファイルを保存した後、Squidを再起動して変更内容を反映させます。

```bash
sudo systemctl restart squid
```

## クライアント側での設定
クライアント端末にプロキシ設定（IPアドレスとポート番号）を指定します。

:::note info
***細かい手順については省略しますが、以下の記事で詳しく解説していますので、必要に応じてご参照ください。***
:::

https://qiita.com/free-honda/items/35471fde808a558c81f9

ここでは、EC2インスタンスのパブリックIPアドレスと、動作中のポート番号3128を設定します。

![Screenshot 2025-01-11 at 18.58.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/935ea5f6-5052-3017-8ac5-9cfe8fa75519.png)

## 稼働確認
クライアント端末からインターネットにアクセスし、動作を確認します。***アクセスログを確認することで、プロキシが正常に稼働していることを検証できます。***

![Screenshot 2025-01-11 at 19.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/5168725b-3093-a610-edfe-03e4f4ba4768.png)

### Squidアクセスログの確認
以下のコマンドでログをリアルタイムで確認します。

```bash
sudo tail -f /var/log/squid/access.log
```

**ログ例:**

```/var/log/squid/access.log
[ec2-user@ip-10-0-1-17 ~]$ sudo tail -f /var/log/squid/access.log
1736587176.919     80 xxx.xxx.xxx.xxx TCP_TUNNEL/200 39 CONNECT www.google.co.jp:443 - HIER_DIRECT/172.217.31.131 -
1736587176.920    132 xxx.xxx.xxx.xxx TCP_TUNNEL/200 5405 CONNECT www.google.co.jp:443 - HIER_DIRECT/172.217.31.131 -
1736587176.920    179 xxx.xxx.xxx.xxx TCP_TUNNEL/200 5407 CONNECT www.google.co.jp:443 - HIER_DIRECT/172.217.31.131 -
1736587176.920    180 xxx.xxx.xxx.xxx TCP_TUNNEL/200 5405 CONNECT www.google.co.jp:443 - HIER_DIRECT/172.217.31.131 -
1736587176.921     81 xxx.xxx.xxx.xxx TCP_TUNNEL/200 39 CONNECT www.google.co.jp:443 - HIER_DIRECT/172.217.31.131 -
```

:::note warn
***これで、クライアント端末からの接続が正常にプロキシサーバーを通過していることを確認できます！***
:::

### 確認ポイントと注意点

- **HTTPステータスコード**  
  `TCP_TUNNEL/200` は、プロキシサーバーがリクエストを正常に中継したことを示しています。

- **プロキシ設定の確認**  
  クライアント端末で設定したプロキシ情報に誤りがある場合、インターネットへの接続に失敗することがあります。

## まとめ
ここまでお読みいただきありがとうございました。 ***プロキシサーバーの構築に関しては、以前からローカル環境での経験や実務での取り扱いがあったため、大きくつまずくことはありませんでした。***

:::note info
**ただし、Squidの設定ファイルを頻繁に触る機会は少ないため、久しぶりの操作で忘れている部分も多く、良い復習の機会となりました。**
:::

***今回の技術検証が少しでも参考になり、どなたかの技術の支えになれば幸いです！***

## 関連記事

https://qiita.com/free-honda/items/27a201413787414b0108

https://qiita.com/free-honda/items/8a5ef34fbfdf268fbb7b



https://qiita.com/free-honda/items/abaf49ad8ce065dc59f1