NginxのリバースプロキシがIPv6で接続しない

前回のブログでIPアクセス制限について書きましたが、その続きで、リバースプロキシ(Nginx)から、オリジンサーバ(inner.taiyodo.ga)へのアクセスがIPv4になってしまい、IPv6での制限解除がなかなかできなかった、という話です。

IPv4の外部アドレスは頻繁に変わるため、そのたびにオリジンサーバの.htaccessを編集する必要がありました。そこで、ほぼ固定のIPv6のサブネットプレフィックスで制限解除しようとしました。

まず、解除するアドレスですが、リバースプロキシサーバでIPv6のグローバルアドレスを確認します。

$  ip address show scope global
2: wlp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet 192.168.XX.XX/24 brd 192.168.XX.XXX scope global noprefixroute wlp1s0
       valid_lft forever preferred_lft forever
    inet6 2404:7a82:6d20:5b00:XXXX:XXXX:XXXX:XXXX/64 scope global dynamic noprefixroute 
       valid_lft 275sec preferred_lft 275sec

上記「2404:7a82:6d20:5b00:XXXX:XXXX:XXXX:XXXX/64」の部分がそれです。CIDRの「/64」がプレフィックス長。英数字1文字で4bit、「:」で区切られた1つが4文字で16bitなので、4つ分で64bitになります。ということで、サブネットプレフィックスは「2404:7a82:6d20:5b00::/64」となるので、.htaccess には以下のように書きました。

Require ip 2404:7a82:6d20:5b00::/64

で、hostsを書き換えたWindowsからChromeでリバースプロキシにアクセスしても Forbiddenでした。なぜ?

オリジンサーバのアクセスログを確認すると、IPv6でなくIPv4のアドレスでアクセスしていることがわかりました。

リバースプロキシからオリジンサーバへ「ping innrt.taiyodo.ga」してもIPv6でアクセスしているし、/etc/gai.cnf 見てもIPv6優先になってるし、NginxがIPv4でしかアクセスしないってのも考えにくいからなんだろなーって考えていたら、なんてことはない、WindowsのhostsでリバースプロキシのIPをIPv4で書いていたからでした。

hosts をIPv6のIPアドレスに変更したら、Forbidden でなく、普通にアクセスできました。

Nginx はIPv4でアクセスされたら、オリジンサーバへもIPv4でアクセスするし、IPv6でアクセスされたら、オリジンサーバへもIPv6でアクセスするということだと思います。

少し調べたけど、根拠となるような情報は見つからなかったので、時間があるときにもう少し調べたいと思います。

残念ながら、しばらくしたらまたForbiddenになりました。

proxy_pass のURLに直接IPv6のIPアドレスを入れればいいことに気づき、こんな感じに設定変更しました。

    location / {
        proxy_pass https://[2404:7a82:6d20:5b00:XXXX:XXXX:XXXX:XXXX]/;
        proxy_set_header Host inner.taiyodo.ga;
        proxy_cookie_domain inner.taiyodo.ga outer.taiyodo.ga;
        proxy_redirect inner.taiyodo.ga outer.taiyodo.ga;
        proxy_http_version 1.1;
        proxy_set_header Authorization "Basic dXNlcjpwYXNzd29yZA==";
    }

proxy_pass にFQDNを指定すれば、HostやSet-Cookie、Locationヘッダなどの書き換えも自動でやってくれますが、IPアドレスを指定した場合はやってくれないため、別で指定しています。

ngx_http_proxy_module のマニュアルを見て知ったのですが、オリジンサーバに接続するときのHTTPのバージョンはデフォルト1.0でした。keepaliveとか使う場合に1.1を推奨と書いてありましたが、なんとなく1.1にしときました。

Nginxの名前解決についての調査は、また次の機会にでも。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です