クラウド上のサーバから、自身の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;
}
}
}