Das ist reproduzierbar mit socat
( 1.7.3.2-2
nicht 1.7.3.1-2+deb9u1
die ignoriert reuseport
) auf Debian (so ähnlich für 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)
Wenn Sie jetzt reuseport
beide hinzufügen :
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
Wenn Sie zum socat
Herstellen einer Verbindung ein anderes oder ein netcat-Gerät verwenden, wird socat
abhängig von der IP-Adresse angezeigt, dass die Verbindung korrekt ist .
Der Verhaltensunterschied hängt also ganz sicher davon ab, wie bind
und setsockopt
unter MacOS und Ubuntu für ssh aufgerufen werden (vielleicht hat launchd auch eine Rolle?). Mit strace
wird dies im Arbeitsfall hinzugefügt socat
:
setsockopt(5, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
UPDATE :
Ich werde mich zwar mit dem Buchstaben der OP-Frage befassen: Damit es funktioniert, denke ich auch, dass die Frage nicht über das umfassendere Ziel aussagt, und dieses Ziel könnte mit einer völlig anderen Lösung erreicht werden.
Um zu ändern sshd
und das ssh
Verhalten beim Binden eines Sockets zu ändern, ist es möglich, einen dlsym()
Wrapper zu verwenden, der das bind(3)
Funktionsverhalten vor dem eigentlichen bind(2)
Syscall ändert .
kompilieren Sie die folgende Datei reuseport-wrapper.c
mit:
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); }
Dadurch wird immer ein Wrapper bind(3)
gesetzt, SO_REUSEPORT
bevor ein inet
oder ein inet6
Socket gebunden wird.
Platziere es irgendwo (zB als /usr/local/lib/reuseport-wrapper.so
aber es ist wirklich egal, da es explizit geladen wird wie ein Plugin).
Bearbeiten /etc/default/ssh
und hinzufügen:
LD_PRELOAD=/usr/local/lib/reuseport-wrapper.so
Starten Sie den SSH-Server neu (zB service ssh restart
)
Führen Sie ein beliebiges anderes Tool (einschließlich ssh
) als root (siehe unten, warum) mit LD_PRELOAD=/usr/local/lib/reuseport-wrapper.so
exported aus. Zum Beispiel:
$ sudo su - [...] # LD_PRELOAD=/usr/local/lib/reuseport-wrapper.so ssh -NfL 127.0.0.2:22:localhost:22 userB@BoxB
Dieser Befehl muss aus zwei Gründen als root gestartet werden: Port 22 erfordert, dass root an ihn bindet, und selbst mit einigen zusätzlichen Funktionen gibt es eine zusätzliche Einschränkung, die in beschrieben wird socket(7)
:
SO_REUSEPORT (seit Linux 3.9)
Lässt zu, dass mehrere AF_INET- oder AF_INET6-Sockets an eine identische Socketadresse gebunden werden. Diese Option muss für jeden Sockel (einschließlich des ersten Sockels) festgelegt werden, bevor bind (2) am Sockel aufgerufen wird. Um das Port-Hijacking zu verhindern, müssen alle an dieselbe Adresse gebundenen Prozesse dieselbe effektive UID haben . Diese Option kann sowohl für TCP- als auch für UDP-Sockets verwendet werden.
Sobald dies erledigt ist:
# 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
Und der Tunnel wird wie erwartet funktionieren.