ネットワークセキュリティ基礎から実践まで 第5編:VPNと暗号化通信
Network Security Series Part 5: VPN and Encrypted Communication
はじめに:安全な通信の核心、暗号化とVPN
現代のネットワーク環境において、データがインターネットを通じて送信される際、そのデータは多数のルーターやネットワーク機器を経由します。この過程で、悪意のある攻撃者がデータを盗聴したり改ざんしたりするリスクが常に存在します。暗号化技術とVPN(Virtual Private Network)は、このような脅威からデータを保護する核心技術です。
今回の第5編では、暗号化の基本概念から始めて、SSL/TLSプロトコル、PKI(公開鍵基盤)、そして様々なVPN技術と実際の構築方法まで詳しく解説します。
1. 暗号化の基礎
暗号化(Encryption)は、平文(Plaintext)を暗号文(Ciphertext)に変換して、権限のないユーザーが内容を理解できないようにする技術です。暗号化方式は大きく共通鍵暗号、公開鍵暗号、そしてハッシュ関数に分けられます。
1.1 共通鍵暗号(Symmetric Encryption)
共通鍵暗号は、暗号化と復号化に同じ鍵を使用する方式です。処理速度が速いですが、鍵交換の問題があります。
主な共通鍵アルゴリズム:
- AES(Advanced Encryption Standard):現在最も広く使用されている共通鍵アルゴリズムで、128/192/256ビットの鍵長をサポートします。
- 3DES(Triple DES):DESを3回適用する方式で、レガシーシステムで使用されます。
- ChaCha20:ソフトウェア実装に最適化されたストリーム暗号で、モバイル環境で人気があります。
- Blowfish/Twofish:ライセンスがフリーなブロック暗号アルゴリズムです。
# PythonでのAES暗号化例
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
# 256ビット鍵の生成
key = get_random_bytes(32)
# 暗号化
cipher = AES.new(key, AES.MODE_CBC)
plaintext = b"This is a secret message"
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
iv = cipher.iv
print(f"IV: {iv.hex()}")
print(f"Ciphertext: {ciphertext.hex()}")
# 復号化
decipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(decipher.decrypt(ciphertext), AES.block_size)
print(f"Decrypted: {decrypted.decode()}")
1.2 公開鍵暗号(Asymmetric Encryption)
公開鍵暗号は、公開鍵(Public Key)と秘密鍵(Private Key)のペアを使用します。公開鍵で暗号化されたデータは、秘密鍵でのみ復号化できます。
主な公開鍵アルゴリズム:
- RSA:最も広く使用されている公開鍵アルゴリズムで、素因数分解の困難さに基づいています。一般的に2048ビット以上の鍵を使用します。
- ECC(Elliptic Curve Cryptography):楕円曲線数学に基づくアルゴリズムで、RSAより短い鍵で同等のセキュリティを提供します。
- Diffie-Hellman:安全でないチャネルで共有秘密を交換するための鍵交換プロトコルです。
- ECDH(Elliptic Curve Diffie-Hellman):ECCを使用したDiffie-Hellmanの変形です。
# PythonでのRSA鍵ペア生成と暗号化例
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
# RSA鍵ペアの生成
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
# 公開鍵で暗号化
recipient_key = RSA.import_key(public_key)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
encrypted = cipher_rsa.encrypt(b"Secret message")
# 秘密鍵で復号化
private_rsa = RSA.import_key(private_key)
decipher_rsa = PKCS1_OAEP.new(private_rsa)
decrypted = decipher_rsa.decrypt(encrypted)
print(f"Decrypted: {decrypted.decode()}")
1.3 ハッシュ関数(Hash Functions)
ハッシュ関数は、任意の長さの入力を固定長の出力(ハッシュ値またはダイジェスト)に変換します。一方向関数であるため、ハッシュ値から元のデータを復元することはできません。
主なハッシュアルゴリズム:
- SHA-256/SHA-384/SHA-512:SHA-2ファミリーで、現在の標準として使用されています。
- SHA-3:Keccakアルゴリズムベースの最新SHA標準です。
- BLAKE2/BLAKE3:非常に高速な暗号学的ハッシュ関数です。
- MD5/SHA-1:脆弱性が発見されており、セキュリティ用途には使用しません。
| アルゴリズム | 出力サイズ | セキュリティ状態 | 用途 |
|---|---|---|---|
| MD5 | 128ビット | 脆弱 | ファイルチェックサム(非セキュリティ) |
| SHA-1 | 160ビット | 脆弱 | レガシーシステム |
| SHA-256 | 256ビット | 安全 | デジタル署名、TLS |
| SHA-3-256 | 256ビット | 安全 | 最新システム |
2. SSL/TLSプロトコル
SSL(Secure Sockets Layer)とTLS(Transport Layer Security)は、ネットワーク通信で暗号化、認証、完全性を提供するプロトコルです。SSLはもはや使用されておらず、現在はTLS 1.2とTLS 1.3が標準です。
2.1 TLSハンドシェイクプロセス
TLS 1.2ハンドシェイク:
- Client Hello:クライアントがサポートするTLSバージョン、暗号スイート、ランダムデータを送信
- Server Hello:サーバーが選択したTLSバージョン、暗号スイート、ランダムデータを送信
- Server Certificate:サーバーの証明書を送信
- Server Key Exchange:鍵交換に必要なパラメータを送信(オプション)
- Server Hello Done:サーバーHello段階の完了を通知
- Client Key Exchange:クライアントがプリマスターシークレットを送信
- Change Cipher Spec:両側が暗号化開始を通知
- Finished:ハンドシェイク完了を確認
TLS 1.3ハンドシェイク(改善点):
- 1-RTT(Round Trip Time)でハンドシェイク時間を短縮
- 0-RTT再接続サポートでさらに高速な接続
- 脆弱な暗号スイートの削除(RC4、3DES、MD5など)
- Perfect Forward Secrecy(PFS)の必須化
2.2 TLS暗号スイート
TLS暗号スイートは、鍵交換、認証、暗号化、ハッシュアルゴリズムの組み合わせです。
# OpenSSLでサポートされる暗号スイートを確認
openssl ciphers -v
# TLS 1.3暗号スイートを確認
openssl ciphers -v -tls1_3
# 推奨暗号スイート例(TLS 1.3)
# TLS_AES_256_GCM_SHA384
# TLS_CHACHA20_POLY1305_SHA256
# TLS_AES_128_GCM_SHA256
# サーバーTLS設定テスト
openssl s_client -connect example.com:443 -tls1_3
2.3 Nginx TLS設定
# /etc/nginx/conf.d/ssl.conf
server {
listen 443 ssl http2;
server_name example.com;
# 証明書設定
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# TLSバージョン設定(1.2、1.3のみ許可)
ssl_protocols TLSv1.2 TLSv1.3;
# 暗号スイート設定
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
# SSLセッションキャッシュ
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS(HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=63072000" always;
}
3. 証明書とPKI(Public Key Infrastructure)
3.1 デジタル証明書
デジタル証明書は、公開鍵と所有者情報を信頼できる機関(CA)が署名した電子文書です。X.509は最も広く使用されている証明書標準です。
証明書の構成要素:
- バージョン(Version)
- シリアル番号(Serial Number)
- 署名アルゴリズム(Signature Algorithm)
- 発行者(Issuer)
- 有効期間(Validity Period)
- サブジェクト(Subject)
- 公開鍵情報(Public Key Info)
- 拡張フィールド(Extensions)
- 署名(Signature)
# 証明書の内容を確認
openssl x509 -in certificate.pem -text -noout
# 証明書チェーンを確認
openssl verify -CAfile ca-bundle.crt certificate.pem
# サーバー証明書のダウンロードと確認
openssl s_client -connect example.com:443 -showcerts
3.2 PKIの構成要素
- CA(Certificate Authority):証明書を発行し署名する信頼機関
- RA(Registration Authority):証明書発行申請を検証する機関
- CRL(Certificate Revocation List):失効した証明書のリスト
- OCSP(Online Certificate Status Protocol):証明書の有効性をリアルタイムで確認するプロトコル
3.3 Let's Encryptを利用した無料証明書の発行
# Certbotのインストール(Ubuntu/Debian)
sudo apt update
sudo apt install certbot python3-certbot-nginx
# Nginx用証明書の発行
sudo certbot --nginx -d example.com -d www.example.com
# 証明書の自動更新テスト
sudo certbot renew --dry-run
# 手動証明書発行(DNS認証)
sudo certbot certonly --manual --preferred-challenges dns -d *.example.com
# 証明書更新クロン設定
# /etc/cron.d/certbot
0 0,12 * * * root certbot renew --quiet
4. VPNの種類
4.1 Site-to-Site VPN
Site-to-Site VPNは、2つ以上のネットワーク(サイト)を接続して、一つの論理的なネットワークのように動作させます。主に本社と支社間の接続に使用されます。
特徴:
- ルーターやファイアウォールレベルで設定
- 永続的な接続を維持
- ネットワーク全体のトラフィックを暗号化
- ユーザーが別途VPNクライアントを必要としない
4.2 Remote Access VPN
Remote Access VPNは、個別ユーザーがリモートから社内ネットワークにアクセスする際に使用します。リモートワーク、出張時によく使用されます。
特徴:
- クライアントソフトウェアが必要
- 必要時に接続/切断
- ユーザー認証が必須
- Split Tunnelingオプションを提供
4.3 SSL VPN vs IPSec VPNの比較
| 特性 | SSL VPN | IPSec VPN |
|---|---|---|
| OSI層 | Application/Transport | Network |
| クライアント | Webブラウザで可能 | 専用クライアントが必要 |
| NAT通過 | 容易 | NAT-Tが必要 |
| ポート | 443(HTTPS) | 500、4500(UDP) |
| 設定の複雑さ | 低い | 高い |
| 使用ケース | リモートアクセス | Site-to-Site |
5. VPNプロトコル
5.1 IPSec(Internet Protocol Security)
IPSecは、IP層で暗号化と認証を提供するプロトコルスイートです。
主な構成要素:
- AH(Authentication Header):完全性と認証を提供、暗号化なし
- ESP(Encapsulating Security Payload):機密性、完全性、認証を提供
- IKE(Internet Key Exchange):セキュリティアソシエーション(SA)の交渉と鍵交換
IPSecモード:
- Transport Mode:IPペイロードのみ暗号化、ホスト間通信
- Tunnel Mode:IPパケット全体を暗号化、VPNゲートウェイ間通信
# strongSwan IPSecのインストール(Ubuntu)
sudo apt install strongswan strongswan-pki
# IPSecの状態確認
sudo ipsec status
# SA(Security Association)の確認
sudo ipsec statusall
5.2 OpenVPN
OpenVPNは、SSL/TLSベースのオープンソースVPNソリューションで、高い柔軟性とセキュリティを提供します。
特徴:
- SSL/TLS使用でファイアウォールフレンドリー
- UDP/TCPをサポート
- カスタム暗号化アルゴリズムの選択が可能
- TAP(ブリッジ)またはTUN(ルーティング)モードをサポート
# OpenVPNサーバーのインストール(Ubuntu)
sudo apt update
sudo apt install openvpn easy-rsa
# Easy-RSAの初期化
make-cadir ~/openvpn-ca
cd ~/openvpn-ca
./easyrsa init-pki
./easyrsa build-ca
# サーバーキーの生成
./easyrsa gen-req server nopass
./easyrsa sign-req server server
# DHパラメータの生成
./easyrsa gen-dh
# TLSキーの生成
openvpn --genkey secret ta.key
5.3 WireGuard
WireGuardは、現代的でシンプルなVPNプロトコルで、最小限のコードベースと最新の暗号化技術を使用します。
特徴:
- 約4,000行のシンプルなコード(OpenVPNの約1/100)
- ChaCha20、Curve25519、BLAKE2sなどの最新暗号化
- カーネルレベル実装による高性能
- シンプルな設定
- UDPベース(TCPは非サポート)
6. WireGuardサーバー構築
6.1 サーバーのインストールと構成
# WireGuardのインストール(Ubuntu 20.04+)
sudo apt update
sudo apt install wireguard
# サーバー鍵ペアの生成
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
# クライアント鍵ペアの生成
wg genkey | tee /etc/wireguard/client1_private.key | wg pubkey > /etc/wireguard/client1_public.key
6.2 サーバー設定ファイル
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY_HERE
# IPフォワーディングとNAT設定
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# クライアント1
[Peer]
PublicKey = CLIENT1_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.2/32
# クライアント2
[Peer]
PublicKey = CLIENT2_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.3/32
6.3 クライアント設定ファイル
# client1.conf
[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY_HERE
Address = 10.0.0.2/24
DNS = 1.1.1.1, 8.8.8.8
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0 # すべてのトラフィックをVPN経由でルーティング
# AllowedIPs = 10.0.0.0/24, 192.168.1.0/24 # Split Tunneling
PersistentKeepalive = 25
6.4 WireGuardサービスの開始
# IPフォワーディングの有効化
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# WireGuardインターフェースの開始
sudo wg-quick up wg0
# 起動時に自動起動
sudo systemctl enable wg-quick@wg0
# 状態確認
sudo wg show
# リアルタイムモニタリング
sudo watch wg show
6.5 ファイアウォール設定
# UFW使用時
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
sudo ufw enable
# iptables直接使用時
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
sudo iptables -A FORWARD -i wg0 -j ACCEPT
sudo iptables -A FORWARD -o wg0 -j ACCEPT
7. SSL VPN設定(OpenVPN)
7.1 OpenVPNサーバー設定
# /etc/openvpn/server.conf
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-GCM
auth SHA256
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log
verb 3
7.2 クライアント設定ファイル生成スクリプト
#!/bin/bash
# generate-client-config.sh
CLIENT_NAME=$1
OUTPUT_DIR="/etc/openvpn/client-configs"
# クライアント鍵の生成
cd ~/openvpn-ca
./easyrsa gen-req ${CLIENT_NAME} nopass
./easyrsa sign-req client ${CLIENT_NAME}
# 設定ファイルの生成
cat > ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn << EOF
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
key-direction 1
verb 3
$(cat /etc/openvpn/ca.crt)
$(cat ~/openvpn-ca/pki/issued/${CLIENT_NAME}.crt)
$(cat ~/openvpn-ca/pki/private/${CLIENT_NAME}.key)
$(cat /etc/openvpn/ta.key)
EOF
echo "Client config created: ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn"
7.3 OpenVPNサービス管理
# サービスの開始
sudo systemctl start openvpn@server
sudo systemctl enable openvpn@server
# 状態確認
sudo systemctl status openvpn@server
# 接続されたクライアントの確認
sudo cat /var/log/openvpn/openvpn-status.log
# ログの確認
sudo tail -f /var/log/openvpn/openvpn.log
8. VPNセキュリティの考慮事項
8.1 認証の強化
- 多要素認証(MFA):証明書 + OTPまたは証明書 + パスワードの組み合わせ
- 証明書ベース認証:共有パスワードより強力なセキュリティ
- LDAP/RADIUS統合:中央集中型ユーザー管理
# OpenVPN LDAP認証プラグイン設定
# /etc/openvpn/auth-ldap.conf
URL ldaps://ldap.example.com
BindDN cn=admin,dc=example,dc=com
Password secretpassword
Timeout 15
TLSEnable yes
BaseDN ou=users,dc=example,dc=com
SearchFilter "(&(uid=%u)(memberOf=cn=vpnusers,ou=groups,dc=example,dc=com))"
RequireGroup true
8.2 ネットワーク分離
- VPN専用サブネット:VPNユーザーを別のネットワークに配置
- アクセス制御リスト(ACL):VPNユーザーがアクセス可能なリソースを制限
- マイクロセグメンテーション:細分化されたアクセスポリシーを適用
8.3 モニタリングとロギング
# WireGuard接続ロギングスクリプト
#!/bin/bash
# /etc/wireguard/log-connections.sh
while true; do
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
wg show wg0 dump | while read line; do
PUBLIC_KEY=$(echo $line | awk '{print $1}')
ENDPOINT=$(echo $line | awk '{print $3}')
LAST_HANDSHAKE=$(echo $line | awk '{print $5}')
RX=$(echo $line | awk '{print $6}')
TX=$(echo $line | awk '{print $7}')
if [ "$LAST_HANDSHAKE" != "0" ]; then
echo "$TIMESTAMP - Peer: $PUBLIC_KEY, Endpoint: $ENDPOINT, RX: $RX, TX: $TX"
fi
done >> /var/log/wireguard/connections.log
sleep 60
done
8.4 セキュリティベストプラクティス
- 強力な暗号化の使用:AES-256-GCM、ChaCha20-Poly1305などの最新アルゴリズムを使用
- 定期的な鍵のローテーション:証明書とPre-Shared Keyを定期的に更新
- Perfect Forward Secrecy:ECDHE鍵交換使用で過去のセッションを保護
- Kill Switch:VPN接続切断時にインターネットを遮断
- DNSリーク防止:VPNトンネル経由でDNSクエリを強制
- Split Tunneling注意:必要な場合のみ使用し、リスクを認識
8.5 VPNプロトコル比較
| プロトコル | セキュリティ | 速度 | 設定難易度 | プラットフォームサポート |
|---|---|---|---|---|
| WireGuard | 非常に高い | 非常に速い | 簡単 | ほとんど |
| OpenVPN | 高い | 普通 | 普通 | すべてのプラットフォーム |
| IPSec/IKEv2 | 高い | 速い | 難しい | ネイティブサポート |
| L2TP/IPSec | 普通 | 普通 | 簡単 | ネイティブサポート |
| PPTP | 脆弱 | 速い | 簡単 | レガシー |
まとめ
VPNと暗号化技術は、現代のネットワークセキュリティの核心要素です。今回の記事で取り上げた内容をまとめると:
- 暗号化の基礎:共通鍵暗号、公開鍵暗号、ハッシュ関数の特性と用途を理解
- SSL/TLS:安全な通信のための標準プロトコル、TLS 1.3の使用を推奨
- PKI:証明書ベースの信頼体系の構築
- VPNの種類:Site-to-SiteとRemote Access VPNの特性を把握
- VPNプロトコル:用途に合ったプロトコルの選択(新規構築時はWireGuardを推奨)
- セキュリティの考慮事項:認証強化、ネットワーク分離、モニタリングが必須
次回の第6編では、WebアプリケーションセキュリティとOWASP Top 10について詳しく解説します。