setcap を使用してポート 80 でローカルホストへのリモート ポート転送を設定するにはどうすればよいでしょうか?

setcap を使用してポート 80 でローカルホストへのリモート ポート転送を設定するにはどうすればよいでしょうか?

NAT を使用しているときに開発のために短時間接続を受け入れたいので、次の操作を実行しようとしています。

$ ssh [email protected] -R 80:localhost:80

低すぎるポートをバインドしようとしているため、失敗します。

Warning: remote port forwarding failed for listen port 80

そこで、1024 未満のポートを listen できるようにする方法があることを発見しました。setcap 'cap_net_bind_service=+ep' /my/applicationそこで、suders crontab に次の内容を追加しました:

@reboot setcap 'cap_net_bind_service=+ep' /usr/sbin/sshd

しかし、まだポート 80 にバインドできません。何が間違っているのでしょうか? 代わりに nginx を使用して 8080 にプロキシするか、iptables などを使用するつもりですが、私がやろうとしたことがなぜ機能しなかったのかまだ不思議です。

答え1

@dwurfの説明にあるように受け入れられた回答は、ユーザーsshに対して 1024 未満のポートにのみバインドしますroot

socatそうでない場合、これは素晴らしい使用例ですroot

8080まず、リモート マシンのポート (またはその他の許可されたポート) にリモート転送を実行します。

ssh [email protected] -R 8080:localhost:80

次に、リモート マシンでポート80をポートにマップします8080

sudo socat TCP-LISTEN:80,fork TCP:localhost:8080

ノート:

Dirk Hoffman の提案どおり、これら 2 つのコマンドを 1 行に組み合わせることができます。

ssh -t [email protected] -R 8080:localhost:80 sudo socat TCP-LISTEN:80,fork TCP:localhost:8080

(パスワード-tを入力するために対話型端末が必要な場合に必要ですsudo。)

答え2

OpenSSH は、ログインしたユーザーのユーザー ID が 0 (root) でない限り、特権ポートへのバインドを完全に拒否します。関連するコード行は次のとおりです。

if (!options.allow_tcp_forwarding ||
    no_port_forwarding_flag ||
    (!want_reply && listen_port == 0) ||
    (listen_port != 0 && listen_port < IPPORT_RESERVED &&
    pw->pw_uid != 0)) {
        success = 0;
        packet_send_debug("Server has disabled port forwarding.");

ソース:http://www.openssh.com/cgi-bin/cvsweb/src/usr.bin/ssh/serverloop.c?annotate=1.1621092-1098行目

興味があれば、pwは型でありstruct passwd *、Linuxでは次のように定義されています。/usr/include/pwd.h

答え3

同様の問題に遭遇したので、最終的に私がたどり着いた解決策は、テーブルのチェーンDNATにルールを追加することでした。OUTPUTnat

iptables -t nat -A OUTPUT -d 127.0.0.0/8 -p tcp --dport 80 \
-j DNAT --to-destination :8080

このルールは、ローカルで生成されたすべての TCP パケットの宛先ポート 80 を 8080 に置き換えます。

着信接続も転送できるようにするには、PREROUTING natチェーンにルールを 1 つ追加します。

iptables -t nat -A PREROUTING -d 10.0.0.200 -p tcp --dport 80 \
-j REDIRECT --to-port 8080

10.0.0.200ウェブサービスへの着信接続を転送するインターフェースのIPアドレスはどこですか?

答え4

解決策の提案の詳細ベン・マレスその上、

以下はワンライナーです:

2 つのリモート ポート転送を開きます:
1. リモート ポート 8888 からローカル ポート 80 へ
2. リモート ポート 8443 からローカル ポート 443 へ

リモート マシンでは、socat は
1. ポート 80 に到着するとポート 8888 にストリーミングされ、
   その後ローカル ホストのポート 80 にトンネルされます
。2. ポート 443 に到着するとポート 8443 にストリーミングされ、
   その後ローカル ホストのポート 443 にトンネルされます。

ssh -t -i ~/.ssh/id_rsa \
    -R 0.0.0.0:8888:0.0.0.0:80 \
    -R 0.0.0.0:8443:0.0.0.0:443 \
    remoteUser@remoteMachine \
    -- "(sudo socat TCP-LISTEN:80,fork TCP:localhost:8888) & \
        sudo socat TCP-LISTEN:443,fork TCP:localhost:8443"

したがって、コマンドを実行する場合は、リモート マシンのルート パスワードを入力する必要があります (ポート 80/443 にリストできるようにするため)。その後 (トンネルが確立されている限り)、リモート ホストのポート 80 または 443 に到着するすべての内容が、それぞれローカル マシンのポート 80 または 443 にトンネルされます...

覚えて!!

すべてのネットワークインターフェース(0.0.0.0)にバインドできるようにするには、リモートマシンを編集し/etc/ssh/sshd_configて設定するGatewayPorts clientspecifiedか、GatewayPorts yes

これをリモート マシンで確認すると、netstat -tlpn | grep -E '8888|8443'次のように表示されます。

tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:8443            0.0.0.0:*               LISTEN      -

そしてそうではない

tcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:8443          0.0.0.0:*               LISTEN      -

関連情報