Verwenden Sie in SSH zwei verschiedene IP-Adressen pro Host

23

Ich habe einen Server mit dem Namen gamma, der ständig in Betrieb ist. Manchmal verbinde ich mich von zu Hause aus damit. In diesem Fall verwende ich die öffentliche IP-Adresse 55.22.33.99. Manchmal verbinde ich mich damit, wenn ich auf der Arbeit bin, und anstatt meine Pakete unnötig herumzuschleudern, verbinde ich mich über die lokale IP - Adresse 192.168.1.100.

Im Moment habe ich sie in zwei verschiedene Einträge aufgeteilt ~/.ssh/conf

Host gamma-local
        HostName 192.168.1.100
        Port 22
        User andreas

Host gamma-remote
        HostName 55.22.33.99
        Port 12345
        User andreas

Wenn ich also auf der Arbeit bin, muss ich nur tippen ssh gamma-localund bin dabei. Wenn ich zu Hause bin (oder irgendwo anders auf der Welt), renne ich ssh gamma-remote.

Wenn ich mich mit dem Server verbinde, müsste ich lieber keinen anderen Namen eingeben, je nachdem, wo ich mich befinde. Ich würde lieber, dass dieser Teil automatisch ausgeführt wird. Zum Beispiel habe ich in einigen Fällen automatisierte Skripte, die eine Verbindung herstellen und nicht wissen, wo ich bin.

Es gibt eine Frage, mit der dieses Problem gelöst werden kann, indem zunächst mit einem Bash-Skript versucht wird, eine Verbindung zum lokalen Skript herzustellen. Wenn dies nicht der Fall ist, versuchen Sie, eine Verbindung zur Remote-IP-Adresse herzustellen. Das ist nett, aber (1) scheint ineffizient zu sein (zumal man manchmal auf eine Verbindungsunterbrechung warten muss, da sie nicht immer sofort einen Fehler zurücksendet) und (2) Bash und das Herumschleppen des Skripts erfordert.

Gibt es eine alternative Möglichkeit, dies zu erreichen, die nicht auf der Verwendung von Bash-Skripten oder dem "Testen" der Funktion der Verbindung als Erstes beruht?

IQAndreas
quelle
Was ich versuche herauszufinden, ist, ob man mit /etc/hostsoder der SSH-Konfigurationsdatei herumfummeln kann, um dies zu erreichen? Oder vielleicht eine Art zu "erkennen", mit welchem ​​LAN Sie gerade verbunden sind?
IQAndreas
Haben Sie einen separaten Satz von Nameservern, die von Ihrem Büronetzwerk verwendet werden?
Sree
@ Sree Ah, ich verstehe, wohin du damit willst. klug! Momentan betreiben wir keinen Nameserver, aber ich könnte definitiv eine der Maschinen in eine umwandeln.
IQAndreas
@Sree Fühlen Sie sich frei, dies auszuarbeiten und als Antwort hinzuzufügen, die mit der Zeile "Wenn Sie einen Nameserver in Ihrem
Büronetzwerk haben
Tat dies. Fühlen Sie sich frei, um hoch / runter zu stimmen :)
Sree

Antworten:

28

Wenn Sie erkennen können, in welchem ​​Netzwerk Sie sich befinden, können Sie das MatchSchlüsselwort in verwenden ~/.ssh/config, um das zu tun, was Sie möchten. Dies erfordert OpenSSH ≥6.5.

Ich benutze etwas Ähnliches wie

Match originalhost gamma exec "[ x$(/sbin/iwgetid --scheme) != xMyHomeESSID ]"
  HostName 192.168.1.100
  Port 22

Host gamma
  User andreas
  Port 12345
  HostName 55.22.33.99

Ich verwende also die Kennung des verwendeten WLAN-Netzwerks, um zu entscheiden, ob ich für die Zwecke der SSH-Verbindung zu Hause bin, überprüfe jedoch die Ihrem Computer zugewiesene IP-Adresse, oder alles andere, was die beiden Netzwerke unterscheidet, kann ebenfalls verwendet werden .

Michał Politowski
quelle
+1 kluger Gebrauch von Match, danke! Es ist möglicherweise eine gute Idee, die Erkennung in ein Skript zu verpacken, das den Beendigungsstatus Null oder Nicht-Null hat, da es dadurch wiederverwendbar wird.
Peterph
@peterph es könnte sicherlich zu einem externen Skript abstrahiert werden, aber ich brauchte nur an einer Stelle bis jetzt, so dass die Dreierregel noch nicht eingetreten ist.
Michał Politowski
Was würde passieren, wenn Sie auf der Arbeit wären, aber tatsächlich eine Verbindung zu einem anderen Computer herstellen möchten? Würde die exec-Anweisung nicht übereinstimmen, da Sie nicht mit Ihrer HomeESSID im WLAN sind und daher den Hostnamen auf 192.168.1.100 setzen?
gegangen
Ich verstehe die Frage nicht. Das Match findet auch auf dem Zielhost statt.
Michał Politowski
1
@typelogic Nicht so einfach, soweit ich weiß. Du könntest es versuchen ProxyCommand nc $address ssh, aber dann z. Haben alle Geräte den gleichen Host-Schlüssel? Wenn Sie dennoch eine Umgebungsvariable festlegen müssen, ist es dann nicht einfacher, die Adresse, mit der eine Verbindung hergestellt werden soll, direkt als Argument sshanzugeben.
Michał Politowski
5

Wenn Sie zufällig einen privaten Nameserver bei der Arbeit haben und von zu Hause und im Büro denselben Laptop verwenden, können Sie dies nutzen, um Folgendes zu erreichen:

  1. Ändern Sie nsswitch.confIhre Einstellungen in Ihrem Computer, um zuerst den DNS einzuchecken
  2. Erstellen Sie einen DNS-Eintrag für gammadie Auflösung auf 192.168.1.100 in Ihrem privaten DNS im Büro.
  3. Erstellen Sie einen Eintrag in der Datei / etc / hosts Ihres Computers, um gammadie Auflösung auf 55.22.33.99 vorzunehmen.

Auf diese Weise ssh gammawird vom Büro-DNS auf 192.168.1.100 aufgelöst, und wenn Sie von zu Hause aus eine Verbindung herstellen, wird von Ihrer Hosts-Datei auf 55.22.33.99 aufgelöst.

PS : Bei dieser Antwort wird davon ausgegangen, dass Gamma keinen öffentlichen DNS-Eintrag haben soll. Wenn Sie von einem Windows-Computer aus SSH-Verbindungen zu Ihrem Server herstellen, sollte es meines Erachtens eine Stelle geben, die der Datei nssswitch.conf entspricht, um die Einträge der Hosts-Datei zu überschreiben.

Sree
quelle
Es gibt - es ist die Hosts-Datei. Und genau so mache ich es - wenn zu Hause meine Public Domain auf meine lokale IP aufgelöst wird. Ausgezeichnete Antwort - es war das erste, woran ich auch dachte. Naja ... heute also, als ich es vor ein paar Jahren eingerichtet habe, musste ich viel googeln, um eine Lösung zu finden.
mikeserv
2

Ich weiß nicht, ob es möglich ist, dies zu tun, ~/.ssh/configaber ein anderer Ansatz wäre, sich auf der Grundlage Ihrer externen IP-Adresse mit dem einen oder anderen zu verbinden. Da Ihre IP-Adresse vermutlich bei der Arbeit liegt, können Sie Folgendes 55.22.33.NNNausführen:

[[ $(wget -qO - http://wtfismyip.com/text) =~ ^'55.22.33.' ]] && 
    ssh 192.168.1.100 ||
    ssh -p 12345 55.22.33.99

Noch einfacher ist es, Ihre interne IP-Adresse zu verwenden. Ich weiß nicht, wie Ihre beiden Netzwerke eingerichtet sind, aber wenn Sie anhand Ihrer IP-Adresse leicht feststellen können, ob Sie berufstätig sind oder nicht (z. B. wenn Sie eine bestimmte IP-Adresse haben, z. B. 192.168.1.12), können Sie Folgendes tun ( Ändern Sie eth0den Namen Ihrer Netzwerkkarte in:

[[ $(ip address show dev eth0 | grep -Po 'inet \K[\d.]+') = '192.168.1.12' ]] && 
    ssh 192.168.1.100 ||
    ssh -p 12345 55.22.33.99

Was auch immer Sie verwenden möchten, Sie können es als Alias ​​zu Ihrer Shell hinzufügen (fügen Sie diese Zeile zur Initialisierungsdatei Ihrer Shell hinzu, ~/.bashrcwenn Sie verwenden bash):

alias gamma="[[ $(wget -qO - http://wtfismyip.com/text) =~ ^'55.22.33.' ]] && ssh 192.168.1.100 || ssh -p 12345 55.22.33.99

Sie können dies auch zu einem Skript machen, wenn andere Skripte darauf zugreifen sollen (Aliase von .bashrcwerden beim Ausführen eines Skripts nicht gelesen).

terdon
quelle
2

Sie können dies nicht erreichen, ~/.ssh/configwenn Sie IP-Adressen als Hostnamen verwenden. Eine zusätzliche Komplikation ergibt sich aus der Tatsache, dass Sie nicht nur eine Verbindung zu verschiedenen IP-Adressen herstellen, sondern auch zu verschiedenen Ports, da so Änderungen an Ihrem DNS-Resolver so gut wie ausgeschlossen sind.

Ich stehe korrigiert - Sie können die Match originalhost ... exec ...Kombo verwenden ~/.ssh/config- siehe @ MichałPolitowski Antwort . Obwohl es für OpenSSH einwandfrei funktioniert, finden Sie ähnliche Funktionen möglicherweise nicht in allen anderen SSH-Clients.

Sie können das Problem umgehen, indem Sie einen einfachen Wrapper (entweder eine Shell-Funktion oder ein Skript, wenn Sie es aus verschiedenen Shells verwenden müssen) verwenden ssh, der überprüft, in welchem ​​Netzwerk Sie sich befinden, und den entsprechenden HostEintrag verwendet. Die große Frage ist, wie Sie zuverlässig erkennen, in welchem ​​Netzwerk Sie sich befinden. Die lokale IP-Adresse kommt in den Sinn, ist jedoch nicht zuverlässig, da Sie möglicherweise auch eine Verbindung über ein LAN herstellen, das dasselbe Subnetz wie Ihr Arbeitsnetzwerk verwendet.

Wenn Sie sowohl für lokale als auch für Remotenetzwerke denselben Port verwenden können, können Sie Ihren Port in /etc/resolv.confAbhängigkeit von dem Netzwerk bearbeiten, in dem Sie sich befinden. Dies müsste natürlich automatisch erfolgen (höchstwahrscheinlich über ein Hook-Skript Ihres DHCP-Clients). Oder - besser - führen Sie einen lokalen Nameserver aus (wie zum Beispiel dnsmasq) und stellen Sie ihm die entsprechende Konfiguration zur Verfügung. Das geht jedoch über den Rahmen dieser Frage hinaus.

Eine andere Option - wenn Sie nur eine interaktive Verbindung herstellen müssen - ist die Verwendung der Befehlsvervollständigung, die gescannt werden würde ~/.ssh/config. Das erspart Ihnen Tipparbeit (vor allem, wenn Sie genügend unterschiedliche HostEinträge haben). So etwas (zur bashInitialisierung):

# complete session names for ssh
declare -g _ssh_complete_hostlist 2> /dev/null
function _ssh_complete_init () {
    _ssh_complete_hostlist=$( \
        sed -nr '/^\s*Host\s*=/{s/^[^=]+= *//;s/ /\n/g;p}' ~/.ssh/config \
        | sort )
}
_ssh_complete_init

function _ssh_complete () {
    local match=${COMP_WORDS[${COMP_CWORD}]}
    local hosts=
    local default=
    for h in $_ssh_complete_hostlist; do
        if [[ $h =~ ^$match ]]; then
            hosts="$hosts $h"
        fi
    done
    if ! (( ${COMP_CWORD} == ${#COMP_WORDS[@]}-1 )); then
        default=$( compgen -f ${COMP_WORDS[${COMP_CWORD}]} )
    fi
    COMPREPLY=($hosts $default)
}
complete -F _ssh_complete ssh

Die erste Funktion erstellt eine Liste, aus der die Hosts vervollständigt werden (normalerweise ist es ausreichend, diese einmal in jeder Shell auszuführen), die zweite Funktion führt die eigentliche Vervollständigung durch, obwohl dies etwas umständlich ist - sie vervollständigt den Hostnamen nur, wenn dies der Fall ist das letzte Token in der Befehlszeile.

Der richtige Weg, um dieses Problem zu lösen, besteht darin, sich über ein VPN mit dem Arbeitsnetzwerk zu verbinden und die lokale Arbeits-IP-Adresse so zugänglich zu machen, als wären Sie im Büro. Sie können dann fest verdrahten die Adresse in was auch immer je nachdem , welche Ebene , die Sie bevorzugen: ~/.ssh/config, /etc/resolv.confoder (imho beste Option) Office - Name - Server.

peterph
quelle
Die Häfen sind nicht in Stein gemeißelt. Ich könnte definitiv den lokalen SSH-Port so ändern gamma, dass er mit dem Remote-Port übereinstimmt, wenn dies die Dinge einfacher machen würde.
IQAndreas
2

Vor einigen Jahren habe ich ein Programm für einen ähnlichen Zweck geschrieben. Es könnte Ihren Bedürfnissen entsprechen. Mit diesem Programm könnte die ssh-Konfiguration so aussehen:

Host gamma
    ProxyCommand ssh-multipath-proxy 192.168.1.100:22 55.22.33.99:12345
    User andreas
Kasperd
quelle
1

Eine weitere Lösung besteht darin, zwei verschiedene Konfigurationsdateien für SSH zu verwenden. Sie mögen dies für etwas weniger elegant halten, als alles in einer Konfigurationsdatei zu haben, aber es ist einfacher zu pflegen.

Sie wählen die Konfigurationsdatei aus, mit der Sie arbeiten möchten -F <configfile>.

Marcel Loose
quelle
Vielen Dank. Ich mag die -FOption.
typelogic
0

Teilantwort:

Viele der obigen Antworten beginnen mit "Wenn Sie feststellen können, in welchem ​​Netzwerk Sie sich befinden". Hierzu verwende ich ein Skript, das ausgeführt wird, wenn Schnittstellen verbunden sind, um verschiedene Dinge (normalerweise VPNs) zu starten, wenn ich eine Verbindung zu einem meiner üblichen Netzwerke herstelle. Die Technik besteht darin, ARP zu verwenden, um die MAC-Adresse des Gateways zu erhalten:

function identifyConnection {
    gatewayIP=$(route -n | grep -e '^0\.0\.0\.0' | tr -s ' ' | cut -d ' ' -f 2)

    if [[ ! -z "$gatewayIP" ]]
    then
        # Identify the gateway by its MAC (uniqueness...)
        log "Gateway IP address=$gatewayIP"
        log "Obtaining corresponding gateway MAC address"
        gatewayData=($(arp -n $gatewayIP | grep -e $gatewayIP | tr -s ' '))
        if [[ "${gatewayData[1]}" == "(incomplete)" ]]
        then
            log "Status of gateway $gatewayIP "incomplete""
            echo ""
        elif [[ "${gatewayData[2]}" == "--" ]]
        then 
            log "No MAC address found for $gatewayIP"
            echo ""
        else
            log "Gateway MAC address=[${gatewayData[2]}]"
            echo "${gatewayData[2]}"
        fi
    fi
}

Und dann habe ich eine Nachschlagetabelle zum Zuordnen des Netzwerks zum Gateway-MAC. Natürlich kann diese Tabelle mehrere MACs für dasselbe Netzwerk enthalten (typischer Fall sind die verschiedenen Wifi-Hotspots auf einer großen Unternehmensseite). Eine andere Nachschlagetabelle wird verwendet, um das für dieses Netzwerk auszuführende Skript zu bestimmen.

In meinem Fall wird das Skript mithilfe der Plasma-Desktop-Benachrichtigungen ausgeführt, sodass sich alles im Benutzerland befindet.

Magnet
quelle