web-dev-qa-db-ja.com

SSLHの透過モードはどのように機能しますか?

TCP接続をポート443で受け入れる必要があるサーバーがあります。接続がOpenVPNクライアントなのかHTTPSクライアントなのかを判断し、それをWebサーバーまたはOpenVPNサーバーに転送します。

SSLHはこの理由のために特別に設計されており、うまく機能しているようです。唯一の問題は、非透過モードで設定すると問題なく機能する一方で、透過モードを使用すると問題が発生することです。

誰かが透明モードがどのように機能することになっているのかの背後にある理論を説明できますか?

SSLHガイドでは、SSLHを透過的に使用するために を指定する必要があります。

  • Sslh.cfgをtransparent: true; に設定します
    • 私はこれをやった
  • sslhには拡張権限が必要です(CAP_NET_ADMIN)
    • Systemd用のsslh.serviceに付属するCentOS 7のリポジトリからsslhをインストールしました。そのサービスファイルにはCapabilityBoundingSet=... CAP_NET_ADMIN ...という行が含まれているので、これはSystemDによってすでに行われていると思います
  • パケットをマークするiptablesルールと、ある種のローカルルートを設定します
    • これは私にはよくわかりません。これらはSSLHサーバーでセットアップされますか?または、OpenVPNサーバーとHTTPSサーバーでセットアップを取得しますか?

この例では、iptablesは、22または4443の送信元ポートを持つすべてのパケットに0x1マーキングを付けるように指示されており、0x1でマークされたすべてのパケットがルーティングテーブル100を使用するようにルールが作成され、ルーティングテーブル100が作成されます。なんらかのローカルルートを設定します。

なぜこれらのiptablesルールとルートが必要なのですか?実際に行っているルートは?ルートはWebサーバーとOpenVPNサーバー上にあり、SSLH ipを指す必要があると思いますが、それも私にはうまくいかないようです。

===

更新:ローカルホストを指すルートである可能性が高いことに気づきました。この例では、サーバーはすべて同じマシン上にあり、実際のサーバーからの応答パケットはSSLHを通過してから、機械。いいですか?もしそうなら、私のサーバーが別のマシン上にある場合、どうしたらいいですか?トラフィックマーキングとそれらのマシンのSSLHサーバーに戻るルートをセットアップしますか?

更新2:SSLHと同じボックスにHTTPSサーバーをすばやくセットアップしましたが、透過モードはSSLHのドキュメントの例とまったく同じように機能しているようです。彼らが別のサーバー上にあるときにそれを動作させる必要があります。

4
Tal

非透過モードでは、クライアントはclient_ip:client_portを使用して、ポート443sslhプロキシに接続します。次に、sslhプロキシは、ポートsslh_ip:sslh_portで内部サーバーへの4443との接続を開きます。内部Webサーバーはweb_ip:4443からproxy_ip:proxy_portに応答します。最後に、sslhプロキシが応答パケットのソースをsshl_ip:443に書き換えて、クライアントに送信します。

sslhプロキシと内部サーバー間の接続の透過モードでは、パケットのソースは元のclient_ip:client_portに設定されます。したがって、内部Webサーバーはclient_ip:client_portをソースとしてweb_ip:4443に直接応答します。ただし、クライアントはproxy_ip:443からのパケットを待機します。

内部サーバーからの回答パッケージの書き換えを管理するには、これらのパッケージをsslhデーモン経由でルーティングする必要があります。デーモンはループバックインターフェイスでクライアントへの回答パッケージを探していると思います。ドキュメントでは、sslhプロキシと同じマシン上のWeb内部サーバーの場合のみが規定されています。

試行錯誤して、私は次の解決策を見つけました:(sslhプロキシ上で)

ip route add local default dev lo table 100
ip rule add fwmark 0x1 lookup 100
iptables -t mangle -N SSLH
iptables -t mangle -A SSLH -j MARK --set-mark 0x1
iptables -t mangle -A SSLH -j ACCEPT

(内部サーバーから回答パッケージをキャッチするため)

iptables -t mangle -A PREROUTING -p tcp -s **web_ip** --sport 4443 -j SSLH

...(ssh、openvpnなどの他のサービスと同様のルール)...

これは、内部Webサーバーのデフォルトルートがsshlプロキシサーバーを経由してインターネットに到達する場合にのみ機能します。

2
Norbert

ありがとうノーバート-あなたは一般的な考えをうまく説明しました。それをすべてまとめると、私が知る限り、これは実行中のすべてのコマンドで具体的に起こっていることです。

SSLHサーバー:

$ Sudo iptables -t mangle -N SSLH
$ Sudo iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j SSLH
$ Sudo iptables -t mangle -A SSLH -j MARK --set-mark 0x1 
$ Sudo iptables -t mangle -A SSLH -j ACCEPT
$ Sudo ip rule add fwmark 0x1 lookup 100 
$ Sudo ip route add local 0.0.0.0/0 dev lo table 100

内部Webサーバー:

$ Sudo iptables -t mangle -N SSLH
$ Sudo iptables -t mangle -A OUTPUT -o eth0 -p tcp -m tcp --sport 4443 -j SSLH
$ Sudo iptables -t mangle -A SSLH -j MARK --set-mark 0x1 
$ Sudo iptables -t mangle -A SSLH -j ACCEPT
$ Sudo ip rule add fwmark 0x1 lookup 100 
$ Sudo ip route add default via [SSLH_IP] table 100 

内部Webサーバー:

  • webサーバー(Apacheやnginxなど)がポート4443でリッスンしている
  • 送信元ポートが4443のeth0から送信されるものはすべてSSLHチェーンに送信されます
  • sSLHチェーン内のすべてのものに0x1のマークが設定されます
  • メインのルーティングテーブルではなく、0x1とマークされたものはすべてルーティングテーブル100を使用する必要があることを示すルーティングルールが作成されます。
  • ルーティングテーブル100には、デフォルトゲートウェイの代わりにSSLHサーバーにトラフィックを送信するように指示するエントリがあります

この一連のイベントにより、基本的に、Webサーバーのプロセス(nginx/Apache /その他)からのトラフィックは、システムの残りのトラフィックのようなデフォルトゲートウェイではなく、SSLHサーバーにルーティングされます。

SSLHサーバー上:

  • webサーバー(ソースポート4443)から送信されるものはすべてSSLHチェーンに送信されます
  • sSLHチェーン内のすべてのものに0x1のマークが設定されます
  • メインのルーティングテーブルではなく、0x1とマークされたものはすべてルーティングテーブル100を使用する必要があることを示すルーティングルールが作成されます。
  • ルーティングテーブル100には、このルーティングテーブルを使用するすべてのトラフィックをループバックインターフェイスにリダイレクトするように強制することを示すエントリがあります。

この一連のイベントにより、基本的に、内部WebサーバーからのトラフィックはSSLHサーバーのループバックインターフェイスにリダイレクトされ、SSLHプロセスはソースIPとポートを書き換えて送信します。

私がまだ持っている質問:

  • いいですか?
  • iptables -t mangle -A SSLH -j ACCEPT 行う?必要ですか?これはFILTERテーブルではありません-なぜここでトラフィックを受け入れるのですか?
  • 私の場合、SSLHホスト上のiptablesプレルーティングルールは、Norbertのものとは異なって見えます。それはどのように機能しますか?何かが--transparent か否か?
0
Tal

ファイルの--transparentパラメータを使用して、GitHubのドキュメントの手順( https://github.com/yrutschle/sslh/blob/master/doc/config.md )に従いました/etc/default/sslh

Apacheが443ではなくポート4443でリッスンし、OpenVPNも使用している場合の例:

DAEMON_OPTS="--user sslh --transparent --listen 0.0.0.0:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:4443 --openvpn 127.0.0.1:1194 --pidfile /var/run/sslh/sslh.pid"

127.0.0.1:1194をVPN IPアドレスで置き換え、その後に:1194を続ける必要がある場合があることに注意してください( https://github.com/yrutschle/sslh/issues/83#issuecomment-515675186 =)。

IPv6サポートが必要な場合は、0.0.0.0をリモートIPv4/IPv6を指す「デュアルスタック」ドメイン名に置き換え、127.0.0.1をローカルIPv4/IPv6を指すlocalhostに置き換えることができます。 /etc/hostsで正しく構成されています。

Debianで再起動した後に永続化するには、ローカルインターフェイスのこれらのpost-upルールを/etc/network/interfacesの既存の構成の下に追加する必要がありました。

# The loopback network interface
auto lo
iface lo inet loopback
# Configure routing for those marked packets (required by sslh transparent mode for IPv4)
        post-up ip rule add fwmark 0x1 lookup 100
        post-up ip route add local 0.0.0.0/0 dev lo table 100
iface lo inet6 loopback
# Configure routing for those marked packets (required by sslh transparent mode for IPv6)
        post-up ip -6 rule add fwmark 0x1 lookup 100
        post-up ip -6 route add local ::/0 dev lo table 100

そして/etc/sysctl.confのこれらのルール:

# Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination (required by sslh transparent mode)
net.ipv4.conf.default.route_localnet=1
net.ipv4.conf.all.route_localnet=1

ドキュメントには、たとえばiptables-persistentを使用して永続化できるいくつかのiptablesルールもあります(なぜかはわかりませんが、透過モードは、テストしたときにこれらのルールなしで機能しているように見えました)。

# DROP martian packets as they would have been if route_localnet was zero
# Note: packets not leaving the server aren't affected by this, thus sslh will still work
iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP
iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP

# Mark all connections made by ssl for special treatment (here sslh is run as user "sslh")
iptables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f

# Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark)
iptables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f

IPv6の場合:

# DROP martian packets as they would have been if route_localnet was zero
# Note: packets not leaving the server aren't affected by this, thus sslh will still work
ip6tables -t raw -A PREROUTING ! -i lo -d ::1/128 -j DROP
ip6tables -t mangle -A POSTROUTING ! -o lo -s ::1/128 -j DROP

# Mark all connections made by ssl for special treatment (here sslh is run as user "sslh")
ip6tables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f

# Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark)
ip6tables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f
0
baptx