IPv4/v6デュアルスタック環境におけるLet's EncryptとSEIL/x86

Posted on 2017/06/22(Thu) 22:05 in technical

前書き

大したことが書いてあるわけではなく、 Certbotを題材にSEIL/x86のポリシールーティングが動く実例を書いてみようと思った次第です。

状況設定

今までIPv4でWebサービスを提供していたけど、昨今の情勢に伴ってIPv6アドレスもサーバーに付与することになり、 結果的に、以下のようなネットワーク構成となったと仮定してください。

0622a_seil_x86_certbot_001.png

そして、サブドメインを含んだ example.com, www.example.com のSSL証明書を発行することを考えます。

SSL証明書発行

さて、既にWebサーバーが動いているとすると、サーバーを止めないで証明書を発行したいと思う気持ちは止められないでしょう。

今回はCertbotを使った以下のコマンドで証明書を取得したいと考えているとします。

# certbot certonly --agree-tos --webroot -w /var/www/example.com -d example.com -d www.example.com -m root@example.com

SSL証明書発行の認証は example.com の /var/www/example.com/.well-known に置かれた認証用テキストをACMEサーバーが参照することで行われます。

簡単にSSL証明書が発行できるなんて、良い時代になったものです。

ポチっとな。

example.comに到達できないよ!

多分、こんな感じのエラーでした。

produced an unexpected error: Failed authorization procedure.
example.com (http-01): urn:acme:error:connection
:: The server could not connect to the client to verify the domain
:: Fetching http://example.com/.well-known/acme-challenge/qB_4kWIzBN1YoEwSbDR-nsL91UiJuMAwNfH05Zz_MEM: Timeout.

今回の原因

まず、今回のDNSの各レコードは、以下のようになっています。(おさらい)

  • example.com
    • 192.0.2.1
    • 2001:db8::1
  • www.example.com
    • 192.0.2.1
    • 2001:db8::81

example.comにアクセスしようとしているACMEサイトは、IPv6の場合、ルーターにアクセスすることになるので、破棄されてギブアップします。

で、どうやらCertbotは最初にIPv6でアクセスして、失敗したらそこで諦めるっぽいんですよ。

一時的にAAAAの回答を止めて証明書を発行することは出来るんですが、毎回それをやるのもなぁ。と言う気持ちになりました。

(そもそもwww.example.comにアクセスしてくれれば、それで済むんですが)

最初の提案

まぁいいや、IPv6 NATしよう。

と思っていたのですけど、SEIL/x86はIPv6の1:1 NAPTのようなことはできないようです。

はい、没。

通報

FreeBSDでpfを使うなら、シレっと解決できる気がする。(試してはいない)

今回の(無理矢理な)解決

そして、先日SEIL/x86のドキュメントを眺めていたところ filter6 で action forward を使えば対応できるのでは?と言う気付きを得ました。

そして、この action forward は、要するにポリシールーティングなので、パケットの書き換えは一切行われません。

とすると、変な方向には飛ばせるけど、宛先IPは結局ルーターに向いたままになります。

そうだね、loにルーターと同じIPを持たせたら良いね。(暴論)

つまり、絵にするとこうです。(実際はもう少し細かいルールだけど)

0622a_seil_x86_certbot_002.png

コマンドではこんな感じ

ルーター(SEIL/x86):

# filter6 add HTTP_CERTBOT_IN interface pppoe2 direction in action forward 2001:db8::81 protocol tcp srcport 1024-65535 dst 2001:db8::1/128 dstport 80 logging on enable
# filter6 add HTTP_CERTBOT_OUT interface lan1 direction in action forward pppoe2 protocol tcp src 2001:db8::1/128 srcport 80 dstport 1024-65535 logging on enable

Webサーバー:

$ sudo ip addr add 2001:db8::1/128 dev lo

終わり

と言うわけで、特に問題なく証明書の発行が出来ました。

まぁ違うFQDNで部分的に同じIPアドレスを使っている構成もどうなんだ、って感じなんですけど、お安く済ませるならこういう方法もあるということで。

そして、SEIL/x86のポリシールーティングは、自宛パケットでも曲げられる。と言う実に素直な実装でした。

おしまい。