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

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

NAT를 수행할 때 단기 개발 연결을 허용하고 싶기 때문에 다음을 시도합니다.

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

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

Warning: remote port forwarding failed for listen port 80

setcap 'cap_net_bind_service=+ep' /my/application그래서 1024보다 낮은 포트에서 수신 대기 할 수 있다는 것을 알았습니다 . 그래서 저는 suders crontab에 이것을 얻었습니다:

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

하지만 여전히 포트 80을 바인딩하는 것은 허용되지 않습니다. 내가 뭘 잘못했나요? 저는 nginx를 사용하여 8080이나 iptables 등을 프록시할 계획이지만, 제가 하려는 일이 왜 작동하지 않는지 여전히 궁금합니다.

답변1

@dwurf에서 설명했듯이수락된 답변, ssh1024보다 작은 포트만 사용자에게 바인딩됩니다 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

궁금하다면 pwis 유형 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로 스트리밍한
   다음 localhost 포트 80으로 터널링합니다
. 2. 포트 443에 도착하고 포트 8443으로 스트리밍한
   다음 localhost 포트 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      -

관련 정보