nginxを使ってSoftEtherと通常のhttpsバーチャルホストを同じIPに同居させる

Jun 20, 2018 - 2 minutes
動機 https、いいですよね。セキュアです。ちゃんと設定すれば。 最近ではLet’s Encryptとか出てきてオレオレ認証の用事も消えて、 確実かつお手軽になったので、わるい人たちから自サイトに来るお客さんを守るのが当たり前になっています。 httpsはhttpをTLSで暗号化したものです。皆さん知っての通り、443番ポートを使います。 私は、貫通性が高いとても便利なSoftEtherVPNに日々お世話になっています。 httpsとはポートが重複するので、https-altとして8443番ポートに逃がしていました。 ところがある日、とある通信環境において、8443番ポートがフィルタリング対象となり、使えなくなってしまったのです。 なんとかして、VPNを8443番ポートから443番ポートに逃がさねばいけなくなりました。 もちろん、VPN、https共々TLSに依存していて、SNIを用いることでトラフィックを振り分けられると原理的にはわかっており、 パケットキャプチャで確信を深めたものの、いざ自分で実装するとなると安定性と実装力の問題もありなかなか手が付きませんでした。 もちろん、TCPかつTLSでSNI対応なリバースプロキシ/ロードバランサの実装を探し回りました。 そして、今日のお昼、「それ、nginxでできるよ」といういつもの答えにたどり着きました。 ロシア語のサイトにほぼ答えが載っていたので、参考資料を首っ引きしながら、なんとか作業を終えました。 以下はその備忘録です。 サブドメインを当てる 一応、DNSサーバ運用の都合でレコード追加の効果が手元に出るまで、 稀に時間がかかることもあるので、 VPNサーバ用のサブドメインの追加はここで行っておいてください。 IPv4/6両方の疎通等も考えると、既存ドメインのCNAMEがおすすめです。 ここでは、vpn.foo.jpとしています。 nginxの再コンパイル nginxを落として解凍します。 % wget http://nginx.org/download/nginx-1.14.0.tar.gz % tar zxvf nginx-1.14.0.tar.gz % cd nginx-1.14.0 コンパイルに必要なパッケージを入れます。 % sudo apt install build-essential libpcre3-dev libssl-dev zlib1g-dev libxml2-dev libxslt1-dev libgd-dev libgeoip-dev UbuntuServer18.04のaptパッケージ版のコンパイルオプションはこんなでした。 % nginx -V nginx version: nginx/1.14.0 (Ubuntu) built with OpenSSL 1.1.0g 2 Nov 2017 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-mcUg8N/nginx-1.

UbuntuServer16.04->18.04のネットワーク設定と、Unbound on Dockerの話

Jun 18, 2018 - 1 minutes
はじめに systemd-resolvedとかnetplan.ioとかのネットワークの設定周りで新機軸が投入されまくった18.04ですが、 0からのセットアップならいろいろ罠は少ないので、既存のドキュメントでなんとかなると思います。 しかし、16.04から18.04のアップデートでネットワーク設定を安定させて、 なおかつ、ローカル用のDNSキャッシュサーバを運用するためには、 そこそこ手間がかかるのでここにメモしておきます。 UnboundとはDNSキャッシュサーバです。 なぜUnboundか、というのはWeb上の記事に書き散らされているのでここでは割愛。 netplan.ioの設定をちゃんとやる netplan.ioはyamlによるネットワーク設定の抽象レイヤです。 要するに、うまい具合にUbuntu全体のネットワーク構成をまとめてしてyamlに書けるようにしたもの……。 と言いたいのですが、NetworkManagerが絡んでくると、NetworkManagerに全部投げるという設定を書くだけの クソみたいなファイルに成り下がるので、現状UbuntuServerでしか利潤を享受できていないように見えます。 apt install netplan.ioで入ります。apt install netplanとか書くと謎のパッケージが入ってわけがわからないことになるので、注意してください。 とりあえず疎通が取れるようにするには、まずここから。 neplan.ioを使うならば、ifupdownはとっとと消し飛ばしたほうがいいです。 特に、sysmted-networkd systemd-resolvedの取扱に苦労しますので、潔く消し飛ばすことを推奨します。 /etc/netowrk/interface(.d/\*)?に該当する設定は、なんだかんだいってかなり書けます。 書き方は、 Examples | netplan.ioとかに転がっているので、 ほとんどの構成はこれで問題ないと思います。 ただし、設定ファイルの拡張子をyamlとしないと読み込まれませんし、 YAMLの文法ミスのデバッグはとても厄介なので、エディタのプラグインでうまい具合にすることを推奨します。 上記の2点に関して注意しないと、netplanのデバッグ出力を見て、キーと値の対応関係が壊れた設定や、 中身のない設定を読み込み続けているのに気づくまでに時間を溶かします。それだけ注意。 netplan.ioをここまでして推す理由はとても明快で、 # netplan tryで設定適用がタイムアウトによるロールバック付きでできるからです。 ifupdown時代のエラーが起きたら諦めるシェル芸を毎回せずに済むのは非常に良いことだと思います。 遠隔からのネットワーク設定適用はなるべくしたくないものですが、かなりハードルが下がりました。 resolvconfを消し、systemd-resolvedを動作させる systemd-resolvedを有効にしたあと、resolvconfを消します。 16.04からのアップデートだとこのパッケージが残っています。 消す順番を間違えると、名前解決ができなくなって、resolv.confに手を入れることになります。 場合によっては、各種設定の問題で正しくsystemd-resolvedが上がってこない場合があるので、ひたすらデバッグします。 /etc/systemd/resolv.confあたりのDNS=にお好みのDNSサーバを入力して、 systemd-resolvedを再起動すればだいたいなんとかなります。 UnboundをDockerで立てる この項の一番下にdocker-compose.ymlがあります。 今回用いるリポジトリはこれです。 mvance/unbound - Docker Hub まずネットワーキングについて。 有無を言わさずhostネットワークを使うのはダサいですが、 一つしか立っていないことを保証するには多分これが一番良い手だと思います。 次にポートについて。 systemd-resolvedがスタブリゾルバを立てて53番ポートを専有しているので退いてもらう必要がありますが、 先にこのスタブリゾルバを殺してしまうと、名前解決ができずにイメージを持ってこられません。 予めをpullしておくか、一度ポート専有で立ち上がらないと怒られる必要があります。 イメージを持ってこれたら、/etc/systemd/resolv.confでDNSStubListener=noとし、systemd-resolvedを再起動します。 加えて、ポートを空けてもらったはいいが、そのまま標準設定で立ち上げると、 digの結果に;; reply from unexpected source: 127.0.0.1#53, expected 127.0.0.53#53と出ます。 localhostにリゾルバが立つので、ループバックインタフェースを使って問い合わせたものの 応答するアドレスが期待と食い違うので応答を拒否する現象が発生しているわけです。

TFTP設定流し込みによる遠隔作業事故

May 7, 2018 - 1 minutes
TL;DR Gitで設定バージョン管理 実家から自宅のサーバへ接続 同セグメントのルータへTFTP設定流し込み 流し込みファイルを誤選択 設定保存コマンド入り 自宅接続断発生 今後の対策 死活監視 設定保存コマンドを確認するまで流さない 死亡時の復旧手法確立 設定を保存しない PDUによるリブート 最終生存時の設定から復旧するバッチ Raspberry Pi設置 LTE回線接続端末として利用 バッチ動作ノードとして利用 背景 自宅,実家,祖母宅の3拠点にRTX810を導入しており、各々設定ファイルを RTX810-(設置場所市名) で同じディレクトリに配置し、Gitでバージョン管理。 設定変更時は、設定ファイルを編集してコミットの後、Githubへプッシュ。tftpで転送して、問題なければルータにて設定保存していた。 事故内容 事故直前までの経緯 実家から実家と自宅、2拠点間のIPsec-VPNの設定を試みていた。 実家から自宅拠点のサーバServer-AへSSHでアクセスし、その環境にて自宅ルータRTX810-A, 実家ルータRTX810-Bの設定ファイルを編集。コミットを重ねていた。 tftpで設定を流し込む際、RTX810-AにはServer-Aを用いて、RTX810-Bには手元端末Client-Bを用い、設定ファイルの融通にはGithubを利用していた。 その際、同じディレクトリにRTX810-Aの設定とRTX810-Bの設定を配置した状態であった。 事故 Server-AからRTX810-Aへの設定流し込み時に、tftpのコマンドを間違え、RTX810-Bの設定をRTX810-Aへ流し込んでしまった。 復旧不可 RTX810-Aの設定ミスによる接続断は想定されており、RTX810-AのLTE回線からGoogleCloudPlatformへ張られたVPNを用いての復旧が想定されていた。 しかし、その設定も含めて書き換えられてしまったため、完全に遠隔からの復旧は不可能になってしまった。 今回は、自宅拠点に人が居なかったため影響しなかったが、転送した設定ファイルは保存コマンドが有効になっていた。 これは、オペレータでない第三者による電源操作を利用した復旧さえ不可能にしてしまう。 対策 そもそも死活監視をしていないので、死活監視を開始して、死亡時になんらかの処理をできるようにする。 復旧手法として、直前の設定を流し込む方式と、単純に設定転送時には保存コマンドを入れずに、PDUを用いて電源断を行う手法がある。 いずれも、意図しない設定の巻き戻りや、意図しない電源断を招く可能性があるので、死活判定時の死亡判定、復旧実行頻度をよく検討する必要がある。 1番簡単な手法として、各拠点にモバイル回線を用意したRaspberry Piを置くことだという指摘を頂いた。確かにそう。確かにそうだが。追加で月額800円(SIM追加2枚)を払うのは、上記に挙げた仕組みをラズパイで実現し維持するコストとどちらが安いのだろうか……。たしかに、仕組みの維持に1時間取られただけでパートタイム時給ですらペイできてしまう。うーむ。