Tronde
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Guten Morgen Gemeinschaft, um von meinem Client einen Reverse-SSH-Tunnel zu meinem Server aufbauen zu können, welcher nach der Provider-Zwangstrennung automatisch wieder aufgebaut wird, verwende ich folgende Service-Unit: 1
2
3
4
5
6
7
8
9
10
11
12 | [Unit]
Description="Reverse ssh tunnel to proxy"
After=network.target
[Service]
User=tronde
ExecStart=/bin/ssh -NTi /home/tronde/.ssh/rsa.id -o ServerAliveInterval=60 -R 22222:localhost:22 tronde@server
RestartSec=30
Restart=always
[Install]
WantedBy=multi-user.target
|
Nun gelingt der Wiederaufbau der Verbindung nicht immer. Auf dem Server finde ich in diesem Fall folgendes im auth-Log: | Jan 7 05:43:45 host sshd[23867]: pam_unix(sshd:session): session opened for user tronde by (uid=0)
Jan 7 05:43:45 host systemd-logind[967]: New session 6795 of user tronde.
Jan 7 05:43:46 host sshd[24030]: error: bind: Address already in use
Jan 7 05:43:46 host sshd[24030]: error: channel_setup_fwd_listener_tcpip: cannot listen to port: 22222
|
Ich nehme an, dass die Verbindung bei der Zwangstrennung nicht sauber abgebaut wird und noch halboffen ist. Deshalb kann der Port nicht erneut gebunden werden, da der Server glaubt, dass hier bereits ein Dienst lauscht und der Port nicht freigegeben wurde. Kann ich etwas tun, damit der Server den Verbindungsabbruch schneller erkennt und den Port freigibt? Oder bleibt mir nichts anderes übrig als den TCP-Timeout abzuwarten? Wie kann ich auf dem Server prüfen, wie hoch der TCP-Timeout eingestellt ist? Kann ich diesen für einzelne Verbindungen senken? MfG Tronde
|
Into_the_Pit
Ehemalige
Anmeldungsdatum: 25. Juni 2008
Beiträge: 9490
Wohnort: Bochum
|
Tronde schrieb: Kann ich etwas tun, damit der Server den Verbindungsabbruch schneller erkennt und den Port freigibt? Oder bleibt mir nichts anderes übrig als den TCP-Timeout abzuwarten?
Spontan fällt mir da ServerAliveInterval und ServerAliveCountMax ein in der SSH-Config vom Client.
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Auf der Seite des Clients kann ich das Problem fürchte ich nicht lösen, da die Verbindung durch die Zwangstrennung ja in jedem Fall abbricht. Diese trennt ja selbst dann, wenn aktiv Daten übertragen werden. Daher denke ich, dass ich nur versuchen kann, den Server dazu zu bringen, den Port früher wieder freizugeben. Oder alternativ das Restart-Intervall der Service-Unit zu erhöhen. Ich kann gerade nicht in die Logs des Clients gucken. Ich vermute, dass er ein Limit für Startversuche hat, welches überschritten wird.
|
Into_the_Pit
Ehemalige
Anmeldungsdatum: 25. Juni 2008
Beiträge: 9490
Wohnort: Bochum
|
Tronde schrieb: Daher denke ich, dass ich nur versuchen kann, den Server dazu zu bringen, den Port früher wieder freizugeben.
Dazu müsstest Du den Socket aus seinem TIME_WAIT Status vorzeitig bekommen. Siehe auch Berkeley_sockets.
Wie kann ich auf dem Server prüfen, wie hoch der TCP-Timeout eingestellt ist?
In /proc/sys/net/ipv4/ z.B. findest Du einige Einträge mit tcp u.a. auch die Keepalive-Intervale, Versuche und Zeit. Zudem noch die Retries. Alles in allem sollte das nach ~2 Minuten in einen Timeout laufen für gewöhnlich.
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Wenn ich mich nun nicht verguckt habe, beträgt der TCP-Timeout zwei Stunden. Ich überlege noch, ob ich an den Werten des Servers etwas ändere oder das Problem lieber auf Clientseite bearbeite. Da der Tunnel nicht 24/7 verfügbar sein muss, könnte ich nach der Zwangstrennung auch ggf. den TCP-Timeout abwarten, bevor ein neuer Verbindungsversuch gestartet wird. Ich muss da noch einmal drüber schlafen und ein wenig dran herumspielen. Ich melde mich dann hier zurück, wenn ich neue Erkenntnisse habe. MfG Tronde
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Hallo, leider bin ich das Problem immer noch nicht ganz los. Ich habe in dem von Into_the_Pit genannten Verzeichnis nach der TCP-KeepAliveTime gesucht und in /proc/sys/net/ipv4/tcp_keepalive_time den Wert 7200 gefunden. Mein Gedanke war nun, dass wenn der Linux-Server den Socket nach spätestens zwei Stunden Leerlauf freigibt, es ausreichen müsste, wenn ich den Parameter 'RestartSec=7201' für meinen Dienst auf dem Client setze, damit dieser sich erst nach dem Timeout wieder mit dem Server verbindet. Leider laufe ich damit immer noch in den eingangs beschriebenen Fehler. Nun habe ich mir einen zweiten Pi mit der gleichen Service-Unit aufgesetzt, um das Problem besser analysieren zu können. Im Moment versuche ich das Problem zu reproduzieren, was mir jedoch nicht gelingen will. Da ich an einem Anschluss ohne Zwangstrennung hänge, versuche ich diese zu simulieren. Dazu habe ich den Prozess auf dem Client schon mit kill -9 PID getötet und das Netzwerkkabel gezogen und nach einigen Sekunden wieder gesteckt. Jedoch gelingt es mir nicht, den Fehler zu reproduzieren. In beiden Fällen kann ich sehen, dass der Server noch auf dem konfigurierten Port lauscht, da er weder ein 'FIN' noch ein 'RST' für die offene Verbindung empfangen hat. Jedoch funktioniert die Verbindungswiederherstellung von diesem Punkt aus bisher reibungslos. Ohne das Problem jedoch reproduzieren zu können, sehe ich keine Möglichkeit, der Fehlerursache auf die Spur zu kommen. Hat von euch noch jemand eine Idee? MfG Tronde
|
lubux
Anmeldungsdatum: 21. November 2012
Beiträge: 14296
|
Tronde schrieb: Nun habe ich mir einen zweiten Pi mit der ... ... Dazu habe ich den Prozess auf dem Client schon mit kill -9 PID getötet und das Netzwerkkabel gezogen ...
Kleine Anmerkung am Rande: Beim PI sollte man nicht das Netzwerkkabel ziehen, sondern m. E. besser:
sudo shutdown -r 1
oder (wenn poweroff)
sudo shutdown -h 1
und erst nach ca. 1.25 Minuten, das Netzwerkkabel ziehen. Zum killen, statt mit "-9", erstmal mit "-15" versuchen:
sudo kill -15 <PID>
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
lubux schrieb: Kleine Anmerkung am Rande: Beim PI sollte man nicht das Netzwerkkabel ziehen, sondern m. E. besser:
sudo shutdown -r 1
oder (wenn poweroff)
sudo shutdown -h 1
und erst nach ca. 1.25 Minuten, das Netzwerkkabel ziehen.
Warum? Kannst du mir erklären, warum das Netzwerkkabel erst nach 1,25 Minuten gezogen werden sollte?
Zum killen, statt mit "-9", erstmal mit "-15" versuchen:
sudo kill -15 <PID>
Dies kommt für meinen Test nicht in Frage. Mit sudo kill -15 wird der Prozess ordentlich beendet. Es findet in diesem Fall ein ordentlicher TCP-Verbindungsabbau statt. Dies ist bei einer DSL-Zwangstrennung, welche ich zu simulieren suche, nicht der Fall.
|
lubux
Anmeldungsdatum: 21. November 2012
Beiträge: 14296
|
Tronde schrieb: Warum? Kannst du mir erklären, warum das Netzwerkkabel erst nach 1,25 Minuten gezogen werden sollte?
Weil "sudo shutdown -h 1" eine (1) Minute für die Ausführung benötigt. Wenn Du es eilig hast, kannst auch mit:
sudo shutdown -h now
versuchen.
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Ok. Hier habe ich aber ebenfalls das Problem, dass die Verbindung ordentlich abgebaut wird. Ich versuche mich ja auf den Fall einzustellen, wo dies nicht passiert und die Verbindung einfach abreißt.
|
lubux
Anmeldungsdatum: 21. November 2012
Beiträge: 14296
|
Tronde schrieb: Ich versuche mich ja auf den Fall einzustellen, wo dies nicht passiert und die Verbindung einfach abreißt.
OK, aber die Verbindung reißt ja nicht ab, weil ein Gerät rebootet wird oder weil ein daemon gekillt wird. Ich denke für deine Simulation, wäre evtl. das tool "tcpkill" geeignet:
tcpkill - kill TCP connections on a LAN
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Hallo, heute habe ich auf dem Client bei der Statusabfrage des reverse_ssh-Dienstes folgende Zeile in der Ausgabe gefunden:
| ssh[16308]: Warning: remote port forwarding failed for listen port 22222
|
Es wird in diesem Fall eine SSH-Verbindung zum Server hergestellt, wo die Weiterleitung an Port 22222 fehlschlägt, weil dieser Port dort noch in Verwendung ist. Nun ist meine Idee, wenn diese Meldung im Journal beim Start der Unit auftritt, den Dienst zu beenden und nach einer gewissen Zeit erneut zu starten. Doch habe ich noch keine Idee wie ich die Service-Unit so gestalten kann, dass nach dem Start das Journal auf diese Zeile geprüft wird. Benötige ich hierzu ein Wrapperskript, welches ich dann in der Service-Unit bei "ExecStart" angebe? Oder habt ihr noch eine bessere Idee? MfG Tronde
|