クラウド上のサーバから、自身のIPアドレスを取得する仕組みが欲しく、ラズパイ4上で、Kubernetes(k3s)で運用しているサーバ上にクライアントのIPを表示するサービスを運用したくなりました。
しかし、このサーバは意外と面倒な構成です。
- ブロードバンドルータという NAT
- LXC 上の nginx で TCP Proxy を動かしている
- k3s 上の nginx で HTTP Proxy を動かしている
- k3s 上で nginx、アプリ間は NodePort でPortを指定している
NAT については、リクエスト元IPを気にする必要はありませんでした。
Service NodePort でリクエスト元IPアドレスを流す
k8s の Service では NAT としてIPアドレスが変わってしまうようです。
spec.externalTrafficPolicy: "Local" に設定することで、リクエスト元のIPを渡すことができると書かれていたので、設定しました。
nginx の HTTP Proxy でリクエスト元IPアドレスを流す
HTTP Proxy には、送信元IPを X-Reql-IP というヘッダーで送る様にしていました。
http { server { listen 30443 ssl; listen [::]:30443 ssl; server_name hogehoge.hogehoge.com; location / { proxy_pass http://raspi:30500; proxy_set_header X-Real-IP $remote_addr; } } }
nginx の TCP Proxy でリクエスト元IPアドレスを流す
これには、proxy_protocol を TCP Proxy のnginxと、それを受ける HTTP Proxyのnginx の両方に対応させる必要がありました。
TCP Proxy の方は以下のような設定です。proxy_protocol on; を付けます。
stream { upstream target { server raspi:30443; } server { listen 443; listen [::]:443; proxy_pass target; proxy_protocol on; } }
HTTP Proxy の方は以下のような設定です。listen に proxy_protocol の記載を追加し、set_real_ip_from で送信元LXCのIP、real_ip_header proxy_protocol;を設定に追加しました。
http { server { listen 30443 ssl proxy_protocol; listen [::]:30443 ssl proxy_protocol; set_real_ip_from 10.42.0.1/24; real_ip_header proxy_protocol; location / { proxy_pass http://raspi:30500; proxy_set_header X-Real-IP $remote_addr; } } }