SSH-Zugriff von innerhalb und außerhalb eines LAN mit demselben Terminalbefehl

10

Ich habe einen Raspberry Pi (RPi) und stelle mit ssh Remoteverbindungen her. Ich habe es geschafft, ssh korrekt einzurichten, sodass ich sowohl über ein lokales Netzwerk als auch über das Internet (über einen bestimmten Port, den ich an meinem Router geöffnet habe) auf das RPi zugreifen kann.

Angenommen, ein Benutzername johnund ein RPi heißen raspi:

Innerhalb des LAN-Zugangs

ssh [email protected]
ssh john@raspi
ssh raspi

Außerhalb des LAN-Zugangs

ssh -p 1234 [email protected]
ssh -p 1234 12.345.67.89

Aber wie kann ich das einfach ssh raspivon außerhalb meines LANs tun ? Gibt es eine Möglichkeit, raspi so zu konfigurieren, dass es auf zwei IP-Adressen verweist, eine in einem LAN und eine über das Internet?

Grundsätzlich möchte ich auf eine einzige Weise auf mein RPi zugreifen, egal ob ich zu Hause oder auf der Arbeit bin.

Aeronaelius
quelle
Sie können einen DNS-Server auf Ihrem lokalen LAN ausführen, der auf die Anfrage nach dem Namen "raspi" mit der IP-Adresse des lokalen LANs reagiert. Wenn Sie nun denselben Namen in eine andere externe Adresse auflösen, muss dieser Name (dynamische DNS) so ausgefüllt werden, dass er auch aufgelöst wird. Aber Sie werden wahrscheinlich einen längeren Namen als "raspi" benötigen.
ChuckCottrill
Siehe diese Fragen und Antworten
slm

Antworten:

7

Bei näherer Betrachtung Ihrer Frage scheint es, dass Sie denselben Computer sowohl innerhalb als auch außerhalb des LAN verwenden. Ich habe meine Antwort entsprechend überarbeitet:

Fügen Sie in Ihrem ~/.ssh/confighinzu:

Host raspi-wan
    HostName 12.34.56.78
    User john
    Port 1234

Host raspi-lan
    HostName 192.168.1.2
    User john
    Port 22

Dann können Sie ssh raspi-wanvon außerhalb des LAN oder ssh raspi-lanvon innerhalb des LAN aus arbeiten, ohne sich mit DNS-Servern herumschlagen oder /etc/hostsfür alle Benutzer bearbeiten zu müssen oder sogar etwas als Root tun zu müssen. Wenn Sie möchten, dass der Name je raspinach Standort unterschiedlich aufgelöst wird, ist wahrscheinlich etwas Shell-Scripting-Magie erforderlich, um Ihr Netzwerk zu erkennen und entsprechend zu handeln.

DopeGhoti
quelle
1
Dank DopeGhoti bin ich sehr zufrieden mit Ihrer Lösung, ein -wanund ein -lanPostfix einzuschließen . Mein ssh mochte das UsernameFeld jedoch nicht (schlechte Konfigurationsoption). Es funktioniert gut ohne es.
Aeronaelius
2
Es tut mir leid, die richtige Syntax ist User johnnicht UserName. Ich korrigiere meine Antwort, um dies widerzuspiegeln, und sobald Sie Ihre Konfiguration festgelegt haben, können Sie den Benutzernamen in der sshBefehlszeile weglassen .
DopeGhoti
5

Dies ist perfekt mit nur der SSH-Konfiguration möglich, ohne dass separate Aliase für LAN und WAN verwendet oder zusätzliche Ports für die Weiterleitung erstellt werden müssen. (Aber Sie brauchen natürlich eine Möglichkeit, um festzustellen, ob Sie sich in Ihrem LAN befinden oder nicht)

In ~/.ssh/configmöchten Sie Folgendes hinzufügen:

Match host raspi exec "am_i_outside_of_my_lan"
    HostName 12.345.67.89
    Port 1234

Anstelle der am_i_outside_of_my_lanSie wollen einen Befehl setzen, ob Sie , wenn Sie außerhalb, und etwas anderes sonst sind in Ihrem Heimnetzwerk oder nicht, und kehrt mit 0 Exit - Code bestimmt.

Die hostBedingung ist wahrscheinlich selbsterklärend, aber die execBedingung verdient eine Erklärung: Sie stimmt nur überein, wenn der angegebene Befehl mit dem Exit-Code 0 zurückgegeben wird, d. H. kein Fehler.

Mit anderen Worten, dies ist der host raspiTeil, auf den diese Regel beschränkt ist, wenn Sie versuchen, eine Verbindung zum Host-Raspi herzustellen, und der exec "am_i_outside_my_lan"weitere, der sie so einschränkt, dass sie nur gilt, wenn Sie eine Verbindung von außerhalb Ihres Heimnetzwerks herstellen. Innerhalb Ihres Heimnetzwerks ssh user@raspimacht es also genau das, was es normalerweise tun würde, aber außerhalb davon stimmt die Regel überein und es macht stattdessen das Äquivalent von ssh -p 1234 [email protected].

Was anstelle von verwendet werden am_i_outside_of_my_lansoll, hängt ganz von Ihrem Setup ab. Ich schlage vor, die Befehle in einem separaten Skript zu platzieren, anstatt zu versuchen, sie inline zu schreiben, da das Zitieren etwas schwierig zu sein scheint.

Persönlich habe ich das folgende Python-Skript verwendet, um festzustellen, ob ich mich in meinem eigenen Netzwerk befinde: (Da mein Domain-Name in eine lokale IP in meinem eigenen Netzwerk aufgelöst wird)

#! /usr/bin/env python
import socket, sys

sys.exit(socket.gethostbyname('mydomain.com').startswith('192.168.1.'))

Wenn Sie kein ähnliches Setup haben, müssen Sie möglicherweise etwas anderes tun. (Sie können beispielsweise den Namen des drahtlosen Netzwerks anzeigen, mit dem Sie verbunden sind, oder sogar einen Dienst für meine IP-Adresse abfragen, um die externe IP-Adresse des Netzwerks abzurufen, mit dem Sie verbunden sind.)

Aleksi Torhamo
quelle
Dies ist die richtige Antwort; Es ist sehr traurig, dass andere mehr Stimmen haben.
Jonathan Tomer
@JonathanTomer: Nun, um fair zu sein, ich habe dies 3 Jahre nach der Frage beantwortet, während die Antworten mit der höheren Punktzahl innerhalb von Stunden veröffentlicht wurden. Es handelt sich also nur um "Der frühe Vogel bekommt den Wurm": P (das habe ich auch zu sagen, dass mir Ellis Hoags spezifische Variante dieser allgemeinen Lösung sehr gefällt - die Verwendung von arp ist ziemlich clever und macht die Lösung allgemeiner, da der Befehl zur Netzwerkerkennung nicht für jedes Netzwerk-Setup
angepasst werden muss
3

Auf Ihrem Computer (die Connect- ing ein), können Sie einen Hostnamen für gesetzt 12.345.67.89. Öffnen Sie Ihre /etc/hostsDatei und legen Sie einen DNS-Eintrag fest:

12.345.67.89    raspi

Ihr Computer wandelt dann "raspi" als Teil eines lokalen DNS-Auflösungsprozesses in "12.345.67.89" um. Wenn Sie mehrere Maschinen verwenden, muss die Änderung an jeder einzelnen Maschine vorgenommen werden. Das Problem ist: Zum Bearbeiten /etc/hostsist Root-Zugriff erforderlich , und Sie haben ihn möglicherweise nicht überall.

Wenn Sie möchten, dass "raspi" von überall automatisch erkannt wird, dann tut mir leid: nicht möglich. Dies würde die Registrierung von "raspi" als Domainnamen erfordern, was nicht passieren kann, da "raspi" keine TLD hat und nicht von einem DNS-Root-Server abhängt. Sie können jedoch einen Domainnamen registrieren (z. B. cfbaptista.meauf Ihre WAN-IP-Adresse verweisen). Mit einigen Portweiterleitungen können Sie auf Ihren Raspberry Pi zugreifen mit:

ssh (you@)(raspi.)cfbaptista.me

(Trotzdem gibt das Geld für fast nichts aus ...)

Das user@Teil hängt von Ihrem Anmeldenamen auf den verschiedenen Computern ab. Wenn Sie auf dem Verbindungscomputer und auf dem Remote- Computer denselben Namen haben, müssen Sie diesen nicht angeben. Wenn nicht, müssen Sie angeben, wer Sie auf dem Remotecomputer sind .

John WH Smith
quelle
Hinweis: Wie in der anderen Antwort erwähnt, können Sie in Ihrer SSH-Konfiguration Host-Aliase erstellen, für die natürlich kein Root erforderlich ist.
strugee
Tatsächlich ! Hier ist ein kleiner Link: kollektividea.com/blog/archives/2011/02/04/how-to-ssh-aliases
John WH Smith
0

Ziel: ssh raspi sollte im LAN und im öffentlichen Internet funktionieren.

Dazu müssen Sie sicherstellen, dass der Name in die interne IP im LAN und die öffentliche IP von außen aufgelöst wird.

Zunächst sollten Sie einen Domainnamen wie erhalten raspi.yourdomain.com. Unter http://freedns.afraid.org/ finden Sie kostenlose Domains für Hobbyzwecke. Zeigen Sie mit der Domain auf Ihre öffentliche IP

Für das LAN empfehle ich, DNSMasq auszuführen. Die offene DD-WRT-Firmware ist eng in DNSMasq integriert und wird für DHCP und DNS verwendet. Sie müssen ihm nur Ihre Suchdomain ("yourdomain.com") mitteilen und es werden automatisch DNS-Namen basierend auf dem angeforderten Namen jedes Clients zugewiesen. Damit dies funktioniert, sollte raspis / etc / hostname lauten raspi.

Sobald dies eingerichtet ist, sollte raspi.yourdomain.com in die lokale IP in Ihrem LAN aufgelöst werden (stellen Sie einfach sicher, dass Sie das lokale DNS auf allen Ihren Computern verwenden).

Jetzt möchten Sie Port 22 wahrscheinlich nicht dem öffentlichen Internet aussetzen, da Sie eine Menge Schnüfflerverkehr erhalten. Möglicherweise stellt Ihr Router raspi: 22 als einen anderen Port bereit, z. B. 1234. Um denselben Port sowohl in öffentlichen als auch in internen Netzwerken zu verwenden, können Sie raspi eine Portumleitungsregel hinzufügen. Unter Linux:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1234 -j REDIRECT --to-port 22
sudo sh -c 'iptables-save > /etc/iptables/iptables.rules'

(Ändern Sie eth0 in den Namen Ihrer Netzwerkschnittstelle, wie durch ip linkoder gezeigt ifconfig, und 1234 in Ihren öffentlichen Port.)

Jetzt können Sie sowohl ssh -p 1234 raspi.yourdomain.comaus dem öffentlichen als auch aus dem LAN.

Sie können einen Eintrag zu ~ / .ssh / config auf Ihrem Client-Computer hinzufügen, um diesen auf nur zu verkürzen ssh raspi, wie von @DopeGhoti erwähnt.

Wenn Sie die SSH-Ports zusätzlicher Computer auf derselben öffentlichen IP-Adresse verfügbar machen möchten, wiederholen Sie den Vorgang einfach mit einem anderen DNS-Namen und einem anderen öffentlichen Port. Prost!

Eric Drechsel
quelle
0

Hier ist eine kurze, funktionierende Version von Aleksi Torhamos Antwort, bei der Curl verwendet wird, um Ihre aktuelle öffentliche IP-Adresse abzurufen und dann zu überprüfen, ob sie mit der öffentlichen IP-Adresse Ihres Servers übereinstimmt (dh Sie befinden sich im selben lokalen Netzwerk).

In Ihrem ~/.ssh/confighinzufügen

Match host raspi exec "[[ $(curl -s ipinfo.io/ip) == '12.345.67.89' ]]"
  User john
  HostName 192.168.2.7

Match host raspi exec "[[ $(curl -s ipinfo.io/ip) != '12.345.67.89' ]]"
  User john
  HostName 12.345.67.89
  Port 1234
Alec Jacobson
quelle
Ich glaube ssh , alle passenden Richtlinien, um verarbeiten, so in der Theorie sollten Sie in der Lage sein , so etwas wie zu tun , Match host raspi / User john / HostName 192.168.2.7gefolgt von Match host raspi exec "[[ $(curl -s ipinfo.io/ip) != '12.345.67.89' ]]" / HostName 12.345.67.89 / Port 1234und den gleichen Effekt mit nur einem bekommen curlAufruf, lassen der == '12.345.67.89'Fall durch den Ausfall der zweiten angenommen wird MatchHerrschaft exec.
FeRD
(Sie müssten nur sicherstellen, dass jedes im ersten angegebene Argument Matchentweder dasselbe oder auch im zweiten Argument ist - wenn Sie Port xxxxim ersten einen Nicht-Standard angegeben haben und im zweiten Matchden Standard-Port verwenden möchten Match, Sie müssten es explizit mit einem überschreiben, Port 22damit es den Port nicht weiter verwendet xxxx.)
FeRD
0

Angenommen, Ihr Computer verfügt über die IP-Adresse 192.168.1. *, Wenn Sie mit Ihrem LAN verbunden sind, können Sie dies mit der folgenden Konfiguration erreichen, ~/.ssh/configsodass Sie immer denselben Befehl (nur ssh raspi) zum Herstellen einer Verbindung verwenden können:

Match Originalhost raspi Exec "ifconfig | grep 192\.168\.1\."
    HostName 192.168.1.2
    User john
    Port 22

Host raspi
    HostName 12.34.56.78
    User john
    Port 1234
Cvuorinen
quelle
0

Bei dieser Lösung wird davon ausgegangen, dass Ihr Heimnetzwerk über einen einzigen Router verfügt, was meiner Meinung nach häufig der Fall ist.

Fügen Sie Ihrem hinzu ~/.ssh/config

Match host raspi exec "test $(arp 192.168.1.1 | awk '{print $4}') = ROUTER_MAC_ADDRESS"
        Hostname 192.168.2.7
        User john

Host raspi
        Hostname 12.345.67.89
        Port 1234
        User john
Ellis Hoag
quelle