LXC、k3s で運用している自宅サーバ nginx Proxy で 送信元IPが知りたい

クラウド上のサーバから、自身の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を渡すことができると書かれていたので、設定しました。

kubernetes.io

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;
        }
    }
}

これで

クラウドから自宅サーバにIPを問い合わせる事ができるようになりました。Proxy 複数あってもなんとかなるものですね。