本文へ移動
vast-cowのブログ
前のページへ戻る

Supermicro X11DPI (ATEN IPMI) を Tailscale Serve で公開するなら、Nginx HTTP Proxy ではなく socat / Nginx stream を使う

この記事を編集

Supermicro X11世代のIPMI(ATENベース)を Tailscale Services (tailscale serve --service) で公開しようとしたところ、意外な落とし穴にはまりました。

結論から言うと、

ATEN IPMIを Tailscale Serve 経由で公開する場合は、HTTPリバースプロキシではなく TCPレベルで中継する構成(socat または Nginx stream)が第一選択です。

やりたかったこと

LAN内のIPMIを

https://x11dpi-ipmi.<tailnet>.ts.net/

のようなサービス名で公開したい。

Tailscale Services を使えば、

tailscale serve \
  --service=svc:x11dpi-ipmi \
  --https=443 \
  https+insecure://x.x.x.x

のような構成が作れます。

しかし、実際にはHTML5 KVMが正常に動作しませんでした。

最初に疑ったのはWebSocket

HTML5 KVMはWebSocketを使用しています。

そのため、

と考えました。

しかし、自作の aiohttp WebSocketサーバーでは正常に動作しました。

つまり、

の組み合わせ自体には問題がありません。

実際の原因

NginxをHTTPリバースプロキシとして挟いて調査すると、

upstream sent invalid header: "\x20..."

というエラーが出ました。

つまり、

502 Bad Gateway

になっています。

これは

ブラウザ
    ↓
Tailscale
    ↓
Nginx HTTP Proxy
    ↓
ATEN IPMI

という構成で、

ATEN IPMIが返すHTTPレスポンスヘッダーをNginxが不正と判断して拒否している

ことを意味します。

GETでは問題なくても、

POST /cgi/ipmi.cgi

のようなCGIでは失敗します。

例えば、

op=UID_SUPPORT.XML

をPOSTすると502になります。

一方、

GET /cgi/ipmi.cgi

は正常に返ります。

つまり、

HTTPレベルの互換性問題です。

これはWebSocketの問題ではない

最初はHTML5 KVMだけが失敗するのでWebSocketを疑いました。

しかし実際には、

CGIのPOSTレスポンスの時点でHTTPパーサが失敗していました。

そのため、

HTML5 KVM以前にIPMIとのHTTP通信自体が成立していません。

解決策1: socat(おすすめ)

HTTPを一切解釈せず、

Tailscale
    ↓ TLS終端
TCP
    ↓
socat
    ↓ TLS
IPMI

という構成にします。

例えば

socat \
  TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork \
  OPENSSL:x.x.x.x:443,verify=0

そして

tailscale serve \
  --service=svc:x11dpi-ipmi \
  --tls-terminated-tcp=443 \
  tcp://127.0.0.1:8082

とします。

この構成では、

すべて正常に動作しました。

HTTPヘッダーを解析しないため、ATEN独自の実装にも影響されません。

解決策2: Nginx stream

NginxでもHTTPではなくstreamモジュールを使えば同様です。

stream {
    server {
        listen 127.0.0.1:8082;

        proxy_ssl on;
        proxy_ssl_verify off;

        proxy_pass x.x.x.x:443;
    }
}

streamはTCPプロキシなので、

HTTPヘッダーを解析しません。

そのためATEN IPMIとの相性問題を回避できます。

Nginx HTTP Proxyはおすすめしない

一般的には

proxy_pass https://x.x.x.x;

というHTTPリバースプロキシを書きたくなります。

しかしATEN IPMIでは、

upstream sent invalid header

になるケースがあります。

これは

以前に、

HTTPレスポンス自体がNginxに拒否されるためです。

バッファサイズや proxy_buffering off などでは改善しません。

なぜsocatが動くのか

socatはHTTPを理解していません。

単なるTCP中継です。

そのため、

ATEN IPMIが多少変わったHTTPレスポンスを返しても、

そのままブラウザへ転送します。

結果として、

ブラウザは問題なく処理できます。

結論

ATENベースのSupermicro X11 IPMIをTailscale Servicesで公開する場合のおすすめ順位は次の通りです。

  1. socat + tailscale serve --tls-terminated-tcp
  2. Nginx stream + tailscale serve --tls-terminated-tcp
  3. Nginx HTTP Proxy(非推奨)

一般的なWebアプリではHTTPリバースプロキシが第一選択ですが、ATEN IPMIでは事情が異なります。

HTTPを解析するプロキシよりも、TCPレベルでそのまま中継する構成の方が安定して動作します。

もし upstream sent invalid header や 502 Bad Gateway に遭遇した場合は、WebSocketやTailscaleを疑う前に、HTTPプロキシを経由していないか確認してみてください。


この記事を編集
この記事を共有:

コメント


前の記事
PiKVMのセットアップと基本的な使い方
次の記事
Rocky Linux 9へUEKを導入する手順(Oracleリポジトリ最小利用)