setcap을 사용하여 포트 80에서 로컬 호스트로의 원격 포트 전달을 어떻게 설정할 수 있습니까?

setcap을 사용하여 포트 80에서 로컬 호스트로의 원격 포트 전달을 어떻게 설정할 수 있습니까?

NAT를 사용할 때 개발을 위해 잠시 연결을 허용하고 싶어서 다음과 같이 하려고 합니다.

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

낮은 포트를 바인딩하려고 하면 실패합니다.

Warning: remote port forwarding failed for listen port 80

그래서 나는 1024보다 낮은 포트를 수신하도록 허용할 수 있다는 것을 발견했습니다 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이 제안한 대로 이 두 명령을 한 줄로 결합할 수 있습니다.

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

( 비밀번호를 -t입력하기 위해 대화형 터미널이 필요한 경우에 필요합니다 sudo.)

답변2

OpenSSH는 로그인한 사용자의 사용자 ID가 0(루트)이 아닌 이상 권한 있는 포트에 대한 바인딩을 거부합니다. 관련 코드 줄은 다음과 같습니다.

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.162라인 1092-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.

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

솔루션 제안에 대해 자세히 설명합니다.벤 마레스위에,

아래는 하나의 라이너입니다.

두 개의 원격 포트 전달을 엽니다.
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 clientspecifiedGatewayPorts 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      -

관련 정보