
Я хотел бы временно принимать соединения для разработки, когда я нахожусь под 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. Итак, у меня в crontab suders есть следующее:
@reboot setcap 'cap_net_bind_service=+ep' /usr/sbin/sshd
Но он все еще не позволяет мне привязаться к порту 80. Что я делаю не так? Я просто собираюсь использовать nginx для проксирования на 8080 или iptables или что-то еще вместо этого, но мне все еще интересно, почему то, что я пытался сделать, не сработало.
решение1
Как объяснил @dwurf'sпринятый ответ, ssh
будет привязан только к портам пользователя меньше 1024 root
.
Это отличный вариант использования, socat
если вы не root
.
Сначала выполните удаленную переадресацию на порт 8080
(или любой другой разрешенный порт) удаленной машины:
ssh [email protected] -R 8080:localhost:80
Затем на удаленной машине сопоставьте порт 80
с портом 8080
:
sudo socat TCP-LISTEN:80,fork TCP:localhost:8080
Примечания:
Как предложил Дирк Хоффман, эти две команды можно объединить в одну строку:
ssh -t [email protected] -R 8080:localhost:80 sudo socat TCP-LISTEN:80,fork TCP:localhost:8080
(Это -t
необходимо в случае, если вам нужен интерактивный терминал для ввода sudo
пароля.)
решение2
OpenSSH категорически откажется привязываться к привилегированным портам, если идентификатор вошедшего в систему пользователя не равен 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.162строки 1092-1098
Если вам интересно, pw
это тип struct passwd *
и в Linux он определен в/usr/include/pwd.h
решение3
Я столкнулся с похожей проблемой, поэтому решение, к которому я пришел, — это добавить DNAT
правило в OUTPUT
цепочку nat
таблиц:
iptables -t nat -A OUTPUT -d 127.0.0.0/8 -p tcp --dport 80 \
-j DNAT --to-destination :8080
Это правило фактически заменяет порт назначения 80 на 8080 для всех локально сгенерированных TCP-пакетов.
Если вы хотите разрешить пересылку любых входящих соединений, добавьте в 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"
Итак, если вы выполните команду, вам придется указать свой пароль root удаленной машины (чтобы иметь возможность просматривать порты 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 -