http及びhttpsの通信を透過的に処理するProxyをAWS上に構築します。
https通信を透過的にproxyするには、一度通信の復号化が必要なため、Squidの「ssl-dump」機能を利用します。
本構成では、機能検証のため冗長性等は考慮していません。本番利用する場合には注意してください。
透過的プロキシの仕組みは以下の記事がすごく参考になりました。 milestone-of-se.nesuke.com
環境
- Amazon Linux2
- Squid : 3.5.20
手順
Squid導入
squidのインストールと自動起動設定をします。
yum install squid -y systemctl enable squid
ssl-dump用証明書作成
opensslで自己証明書を作成します。
openssl req -new -newkey rsa:2048 -sha256 -days 3650 -nodes -x509 -extensions v3_ca -keyout <秘密鍵の出力先>.pem -out <証明書の出力先>.cer
パケットフォワーディングを有効
NATを有効化するためにパケットフォワーディングを有効化します。
echo 1 > /proc/sys/net/ipv4/ip_forward
Iptables 設定
Squidにきたhttp/httpsをSquidの待ち受けポートにポート変換します。(Squidの設定は後ほど)
- 80 ⇒ 3128
- 443 ⇒ 3129
iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 3128 iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 3129
iptablesの設定はOSの再起動でリセットされてしまうので、永続化します。
yum install iptables-services iptables-save > /etc/sysconfig/iptables
Squidファイルの修正
HTTP/HTTPSの透過的Proxyモードを有効化します。
https_port
のssl-dumpの設定(cer=xxx,key=xxx)で先ほど作成した自己証明書のPathを指定します。
</etc/squid/squid.conf> # # Recommended minimum configuration: # # Example rule allowing access from your local networks. # Adapt to list your (internal) IP networks from where browsing # should be allowed 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 SSL_ports port 443 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 CONNECT method CONNECT # # Recommended minimum Access Permission configuration: # # Deny requests to certain unsafe ports http_access deny !Safe_ports # Deny CONNECT to other than secure SSL ports http_access deny CONNECT !SSL_ports # Only allow cachemgr access from localhost http_access allow localhost manager http_access deny manager # We strongly recommend the following be uncommented to protect innocent # web applications running on the proxy server who think the only # one who can access services on "localhost" is a local user #http_access deny to_localhost # # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS # # Example rule allowing access from your local networks. # Adapt localnet in the ACL section to list your (internal) IP networks # from where browsing should be allowed http_access allow localnet http_access allow localhost # And finally deny all other access to this proxy http_access deny all # Squid normally listens to port 3128 http_port 3128 intercept ###HTTPアクセス用 Tranceparentモードの有効化 https_port 3129 intercept ssl-bump cert=xxx.cer key=xxx.pem ###HTTPSアクセス用 Tranceparentモードの有効化&ssldumpの有効化 # Uncomment and adjust the following to add a disk cache directory. #cache_dir ufs /var/spool/squid 100 16 256 # Leave coredumps in the first cache dir coredump_dir /var/spool/squid # # Add any of your own refresh_pattern entries above these. # refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern . 0 20% 4320
設定変更したらSquidを再起動します。
systemctl restart squid
Source/Destチェックの無効化(AWSコンソール上)
AWSコンソール上で、Squidを起動しているEC2の Source/Destチェックを無効化します。
ルートテーブルの修正(AWSコンソール上)
デフォルトゲートウェイをSquidが起動しているEC2のENIに向けます。
この設定をすることで、インターネット向きの通信が全てProxyサーバーを経由するようになります。
通信テスト
デフォルトゲートウェイをProxyサーバーへ向けたサブネット上に、テスト用のEC2を起動し通信テストします。
http
特にプロキシを指定していませんが、問題なくHTMLを取得できています。
# curl http://www.google.com <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="世界中のあらゆるভ 3;報を検索するためのツールを提供しています。さまざまな検索機能を活用して、お探しの情報を見つけてください。" name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8"http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="F1AzvU4PXx3yUsGHOKjBKw==">(function(){window.google= <省略>
https
証明書チェックあり
proxyで設定した自己証明書が原因でエラーとなります。(tlsを復号化しているので、中間攻撃と同じなため)
# curl https://www.google.com curl: (60) SSL certificate problem: self signed certificate More details here: https://curl.haxx.se/docs/sslcerts.html curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above.
証明書チェックなし
エラーを回避するためには、証明書チェックを外します。 curlの場合は、 -k
オプションつけます。
証明書チェックを外した場合は、HTMLが取得できます。
# curl https://www.google.com -k <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="世界中のあらゆる情報を検索するためのツールを提供しています。さまざまな検索機能を活用して、お探しの情報を見つけてください。" name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8"http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="tnfQ1aqNu90PTVnC7FS3wg==">(function(){window.google= <省略>
AWS CLI (https)
証明書チェックあり
AWS CLI実行時も同様で、証明書のエラーがでます。
# aws ec2 describe-instances SSL validation failed for https://ec2.ap-northeast-1.amazonaws.com/ [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:727)
証明書チェックなし
AWS CLI に --no-verify
オプションを追加すると証明書エラーを回避できます。
# aws ec2 describe-instances --no-verify /usr/lib/python2.7/site-packages/urllib3/connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is stronglyadvised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) { "Reservations": [ { "Instances": [ <省略>
最後に
AWS上では普段あまりやらない構成ですが、どなたかの参考になれば幸いです。 本番利用を見据えて冗長化やメンテナンス性を考慮するのであれば、TransitGateway + PaloAltoとかの構成のほうが良いのかなと思いました。 (本稿の構成だと、Squidの冗長化とかルートテーブルの修正とかつらそうなので...)