sshd "прослушивание на всех интерфейсах", OSX и Ubuntu

502
Congee

Учитывая дополнительный интерфейс обратной связи в диапазоне 127.0.0.X( X> 1) на BoxA (который может работать под управлением OSX или Linux), я хочу привязать порт 22 этого дополнительного интерфейса обратной связи к прямому туннелю SSH (т. Е. К локальному порту), который указан в BoxB.

На OSX это работает нормально (странно, оглядываясь назад). [Принятие X= 2] после вызова псевдонима петли с помощью ifconfig lo0 alias 127.0.0.2 upSSH может установить туннель с помощью ssh -NfL 127.0.0.2:22:localhost:22 BoxB. Затем в новой оболочке на BoxA, ssh 127.0.0.2регистрирует меня в BoxB.

В Ubuntu я могу вызвать псевдоним loopback на BoxA, но при попытке установить SSH-туннель sshжалуется на невозможность связать (и, следовательно, переслать) порт 22. BoxA. Последующее ssh 127.0.0.2(в новой оболочке на BoxA) дает предупреждение об отпечатке пальца, которое, если его обойти, регистрирует меня обратно в BoxA. Имеет смысл - sshdна BoxA слушает все интерфейсы.

Глядя на sshd_configкаждый, оба настроены на прослушивание 0.0.0.0::для IPv6).

lsof для OSX дает:

launchd 1 root 40u IPv6 0xddfcabed61001f0d 0t0 TCP *:ssh (LISTEN) launchd 1 root 41u IPv4 0xddfcabed6100413d 0t0 TCP *:ssh (LISTEN) launchd 1 root 43u IPv6 0xddfcabed61001f0d 0t0 TCP *:ssh (LISTEN) launchd 1 root 44u IPv4 0xddfcabed6100413d 0t0 TCP *:ssh (LISTEN) 

и для Ubuntu:

sshd 1287 0 3u IPv4 21903340 0t0 TCP *:ssh (LISTEN) 

Так что оба слушают на всех интерфейсах, хотя я не уверен, почему OSX использует 4 процесса. В любом случае, Ubuntu дает ожидаемое поведение. Почему OSX ведет себя по-другому?

Следующий вопрос, конечно, заключается в том, как заставить Ubuntu вести себя как OSX в этом отношении.

Несмотря на то, что я хотел sshd_configбы иметь состояние, подстановочные знаки и / или логические операторы (например, «не слушайте 127.0.0.*; слушайте 127.0.0.1»), похоже iptables, это не так ...

0
Не нужно играть с X. Просто используйте `ssh -NfL 22: localhost: 22 BoxB` и подключитесь к туннельному порту как localhost: 22 Alex 5 лет назад 0
Это дает сбой channel_setup_fwd_listener_tcpip с «bind: Адрес уже используется» для хорошей меры (в Ubuntu). Congee 5 лет назад 0
Это означает, что вы уже привязали что-то к одному и тому же порту. Если у вас есть несколько туннелей к другим блокам или какой-то локальный сервис, уже использовавший его для какой-то цели, просто используйте другой локальный порт, который не используется: `ssh -NfL 20001: localhost: 22 BoxA`,` ssh -NfL 20002: localhost: 22 BoxB`, `ssh -NfL 20003: localhost: 22 BoxC` и так далее ... Используйте` netstat -lntp` для определения свободных / занятых локальных портов Alex 5 лет назад 0
Да, sshd на BoxA использует порт 22, который хорошо виден в выводе `lsof`. Весь вопрос в том, почему OSX позволяет пересылку: 22 на новых интерфейсах обратной связи, а Ubuntu не ... Congee 5 лет назад 0

1 ответ на вопрос

0
A.B

Это воспроизводимое с помощью socat( 1.7.3.2-2не 1.7.3.1-2+deb9u1который игнорирует reuseport ) на Debian (так похожий на Ubuntu):

term1$ socat -d -d TCP4-LISTEN:5555,reuseaddr,fork - 2018/08/03 08:20:43 socat[25084] N listening on AF=2 0.0.0.0:5555  term2$ socat -d -d TCP4-LISTEN:5555,bind=127.0.0.2,reuseaddr,fork - 2018/08/03 08:21:00 socat[25085] E bind(5,, 16): Address already in use 2018/08/03 08:21:00 socat[25085] N exit(1) 

Теперь, если вы добавите reuseport оба :

term1$ socat -d -d TCP4-LISTEN:5555,reuseaddr,reuseport,fork - 2018/08/03 08:21:28 socat[25086] N listening on AF=2 0.0.0.0:5555  term2$ socat -d -d TCP4-LISTEN:5555,bind=127.0.0.2,reuseaddr,reuseport,fork - 2018/08/03 08:21:56 socat[25092] N listening on AF=2 127.0.0.2:5555   otherterm$ netstat -tnlp 2>/dev/null|grep :5555  tcp 0 0 127.0.0.2:5555 0.0.0.0:* LISTEN 25092/socat  tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 25086/socat  

Использование другого socatили netcat для подключения покажет, что он правильно направлен на правильное прослушивание в socatзависимости от IP-адреса.

Таким образом, разница в поведении, безусловно, о том, как bindи setsockoptзвонки делаются на MacOS и Ubuntu для SSH (возможно, запуск программ имеет роль тоже?). Используя strace, это добавляется в рабочем socatслучае:

 setsockopt(5, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0 

ОБНОВЛЕНИЕ : в
то время как я обращусь к письму вопроса OP: заставьте это работать, я также думаю, что вопрос не говорит о более широкой цели, и эта цель могла бы быть достигнута с совершенно другим решением.

Таким образом, для изменения sshdи sshповедения, когда они связывают сокет, можно использовать dlsym()оболочку, которая изменит bind(3)поведение функции перед реальным bind(2)системным вызовом.

скомпилируйте файл reuseport-wrapper.cниже с помощью:

gcc -shared -fPIC -o reuseport-wrapper.so reuseport-wrapper.c -ldl

#define _GNU_SOURCE #include <dlfcn.h>  #include <sys/socket.h> #include <stddef.h> /* NULL */  int bind(int socket, const struct sockaddr *address, socklen_t address_len) { static const int optval=1; static int (*orig_bind)(int, const struct sockaddr *,socklen_t)=NULL;  if (orig_bind == NULL && (orig_bind=dlsym(RTLD_NEXT,"bind")) == NULL) return -1; if (address != NULL && (address->sa_family == AF_INET || address->sa_family == AF_INET6)) { if (setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof optval) != 0) { return -1; } } return orig_bind(socket, address, address_len); } 

Это установит обертку, bind(3)чтобы всегда устанавливать SO_REUSEPORTперед привязкой inetили inet6сокета.

Поместите его куда-нибудь (например, как, /usr/local/lib/reuseport-wrapper.soно на самом деле это не имеет значения, поскольку он явно загружен как плагин).

Отредактируйте /etc/default/sshи добавьте:

LD_PRELOAD=/usr/local/lib/reuseport-wrapper.so 

перезапустите сервер ssh (например service ssh restart)

И запустите любой другой инструмент (включая ssh) с правами суперпользователя (см. Ниже, почему) с помощью LD_PRELOAD=/usr/local/lib/reuseport-wrapper.soexport. Например:

$ sudo su - [...] # LD_PRELOAD=/usr/local/lib/reuseport-wrapper.so ssh -NfL 127.0.0.2:22:localhost:22 userB@BoxB 

Эту команду нужно запускать с правами root по двум причинам: порт 22 требует привязки к нему root, и даже с некоторыми дополнительными возможностями есть дополнительное ограничение, описанное в socket(7):

SO_REUSEPORT (начиная с Linux 3.9)
Разрешает привязку нескольких сокетов AF_INET или AF_INET6 к одному и тому же адресу сокета. Эта опция должна быть установлена ​​на каждом сокете (включая первый сокет) до вызова bind (2) на сокете. Чтобы предотвратить перехват порта, все процессы, привязанные к одному и тому же адресу, должны иметь один и тот же эффективный UID . Эта опция может использоваться с сокетами TCP и UDP.

Как только это будет сделано:

# netstat -tnlp |grep -w 22 tcp 0 0 127.0.0.2:22 0.0.0.0:* LISTEN 157/ssh  tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 143/sshd  tcp6 0 0 :::22 :::* LISTEN 143/sshd  

И туннель будет работать как положено.

Хорошая информация, спасибо. Не уверен, что я принимаю его как ответ как таковой, так как он не решает проблему (если ее вообще можно исправить), но предоставляет полезную информацию ... Congee 5 лет назад 0
Добавлено «рабочее» решение, чтобы подчеркнуть что-то еще, что нужно искать. Возможно, вопрос скрывается [проблема XY] (https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). A.B 5 лет назад 0
@ Congee, так ты попробовал мое обновление? Это заставляет это работать согласно вопросу, не так ли? Я ответил, почему есть разница, и как заставить это работать на Ubuntu. A.B 5 лет назад 0