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

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

ポート443でTCP接続を受け入れ、接続が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システムを通過したいので、これがlocalhostへのパスである可能性があると思いました。そうだと思いますか?それでは、サーバーが別のコンピューターにある場合はどうすればよいですか?このシステムからSSLHサーバーへのトラフィックの表示とルーティングをリセットしますか?

アップデート2:SSLHと同じマシンにHTTPSサーバーをすばやく設定しましたが、透過モードはSSLHドキュメントの例のように動作するようです。別のサーバーにいるときに機能するにはこれが必要です。

答え1

不透明モードでは、クライアントはポートのプロキシclient_ip:client_portに接続します。その後、プロキシはそのポートから内部サーバーへの接続を開きます。内部Webサーバーがから応答します。最後に、プロキシは応答パケットのソースを書き換えてクライアントに送信します。sslh443sslhsslh_ip:sslh_port4443web_ip:4443proxy_ip:proxy_portsslhsshl_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などの他のサービスに対する同様の規則)...

sshlこの機能は、内部Webサーバーのデフォルトパスがプロキシサーバーを介してインターネットに接続されている場合にのみ機能します。

答え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

答え3

私はGitHubの文書化の手順に従いました(https://github.com/yrutschle/sslh/blob/master/doc/config.md)、--transparentファイルのパラメータを使用します/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"

VPNのIPアドレスに置き換えて、127.0.0.1:1194その後に:1194https://github.com/yrutschle/sslh/issues/83#issuecomment-515675186)。

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

post-upDebian で再起動時に永続的にするには、既存の設定の下にローカルインターフェイスの次のルールを追加する必要がありました。/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ルールもありますiptables-persistent(理由はわかりませんが、テストしたときに透過モードはこれらのルールなしで動作するようです)。

# 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

関連情報