TCP接続をポート443で受け入れる必要があるサーバーがあります。接続がOpenVPNクライアントなのかHTTPSクライアントなのかを判断し、それをWebサーバーまたはOpenVPNサーバーに転送します。
SSLHはこの理由のために特別に設計されており、うまく機能しているようです。唯一の問題は、非透過モードで設定すると問題なく機能する一方で、透過モードを使用すると問題が発生することです。
誰かが透明モードがどのように機能することになっているのかの背後にある理論を説明できますか?
SSLHガイドでは、SSLHを透過的に使用するために を指定する必要があります。
transparent: true;
に設定しますCapabilityBoundingSet=... CAP_NET_ADMIN ...
という行が含まれているので、これはSystemDによってすでに行われていると思いますこの例では、iptablesは、22または4443の送信元ポートを持つすべてのパケットに0x1マーキングを付けるように指示されており、0x1でマークされたすべてのパケットがルーティングテーブル100を使用するようにルールが作成され、ルーティングテーブル100が作成されます。なんらかのローカルルートを設定します。
なぜこれらのiptablesルールとルートが必要なのですか?実際に行っているルートは?ルートはWebサーバーとOpenVPNサーバー上にあり、SSLH ipを指す必要があると思いますが、それも私にはうまくいかないようです。
===
更新:ローカルホストを指すルートである可能性が高いことに気づきました。この例では、サーバーはすべて同じマシン上にあり、実際のサーバーからの応答パケットはSSLHを通過してから、機械。いいですか?もしそうなら、私のサーバーが別のマシン上にある場合、どうしたらいいですか?トラフィックマーキングとそれらのマシンのSSLHサーバーに戻るルートをセットアップしますか?
更新2:SSLHと同じボックスにHTTPSサーバーをすばやくセットアップしましたが、透過モードはSSLHのドキュメントの例とまったく同じように機能しているようです。彼らが別のサーバー上にあるときにそれを動作させる必要があります。
非透過モードでは、クライアントはclient_ip:client_port
を使用して、ポート443
のsslh
プロキシに接続します。次に、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
プロキシサーバーを経由してインターネットに到達する場合にのみ機能します。
ありがとうノーバート-あなたは一般的な考えをうまく説明しました。それをすべてまとめると、私が知る限り、これは実行中のすべてのコマンドで具体的に起こっていることです。
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サーバーのプロセス(nginx/Apache /その他)からのトラフィックは、システムの残りのトラフィックのようなデフォルトゲートウェイではなく、SSLHサーバーにルーティングされます。
SSLHサーバー上:
この一連のイベントにより、基本的に、内部WebサーバーからのトラフィックはSSLHサーバーのループバックインターフェイスにリダイレクトされ、SSLHプロセスはソースIPとポートを書き換えて送信します。
私がまだ持っている質問:
iptables -t mangle -A SSLH -j ACCEPT
行う?必要ですか?これはFILTERテーブルではありません-なぜここでトラフィックを受け入れるのですか?--transparent
か否か?ファイルの--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