Utilizzare due diversi indirizzi IP per host in SSH


23

Ho un server, chiamato gamma, costantemente attivo e funzionante al lavoro. A volte mi connetto ad esso da casa, nel qual caso utilizzo l'indirizzo IP pubblico 55.22.33.99. A volte, mi collego ad esso quando sono al lavoro, e piuttosto che di rimbalzo i miei pacchetti in giro inutilmente, mi collego tramite l'indirizzo IP locale, 192.168.1.100.

Al momento, li ho suddivisi in due voci diverse in ~/.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

Quindi, se sono al lavoro, tutto ciò che devo scrivere è ssh gamma-locale ci sto; se sono a casa (o in qualsiasi altra parte del mondo), corro ssh gamma-remote.

Quando mi collego al server, preferirei non dover digitare un nome diverso a seconda di dove mi trovo, preferirei che quella parte venisse eseguita automaticamente; per esempio, in alcuni casi ho degli script automatici che si collegano e che non sanno dove sono.

C'è una domanda che risolve questo problema utilizzando uno script Bash per "provare" a connettersi prima a quello locale e, se non si connette, provare a connettersi all'indirizzo IP remoto. Questo è carino, ma (1) sembra inefficiente (soprattutto perché a volte devi "attendere" il timeout delle connessioni in quanto non sempre restituiscono immediatamente un errore) e (2) richiede Bash e trascinando lo script.

Esiste un modo alternativo per raggiungere questo obiettivo che non si basa sull'uso degli script Bash, né "testare" per vedere se la connessione funziona per prima?


Quello che sto cercando di scoprire è se si può giocherellare /etc/hostso il file di configurazione SSH per raggiungere questo obiettivo? O forse un modo per "rilevare" a quale LAN sei attualmente connesso?
IQAndreas,

Hai un set separato di nameserver usati dalla tua rete d'ufficio?
Sree,

@Sree Ah, vedo dove stai andando con questo; intelligente! Al momento non abbiamo un server dei nomi, ma potrei sicuramente convertire una delle macchine in una.
IQAndreas,

@Sree Sentiti libero di elaborarlo e aggiungerlo come una risposta che inizia con la riga "Se hai un nameserver sulla tua rete d'ufficio ..."
IQAndreas

Fatto quello. Sentiti libero di votare in alto / in basso :)
Sree

Risposte:


28

Se hai un modo per riconoscere su quale rete ti trovi, puoi usare la Matchparola chiave ~/.ssh/configper fare quello che vuoi. Ciò richiede OpenSSH ≥6,5.

Uso qualcosa di simile a

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

Quindi sto usando l'identificatore della rete wifi usata per decidere se sono a casa ai fini della connessione SSH, ma posso controllare anche l'indirizzo IP assegnato al tuo computer o qualsiasi altra cosa che differenzi le due reti .


+1 uso intelligente di Match, grazie! Potrebbe essere una buona idea racchiudere il rilevamento in uno script in uscita con stato di uscita zero o diverso da zero, poiché ciò lo renderebbe riutilizzabile.
peterph

@peterph certamente potrebbe essere estratto in uno script esterno, ma fino ad ora avevo bisogno di un solo posto, quindi la regola del tre non è ancora entrata in vigore.
Michał Politowski,

Cosa succederebbe se tu fossi al lavoro, ma in realtà vuoi connetterti ad un'altra macchina? L'istruzione exec non corrisponderebbe dal momento che non sei su WiFi con il tuo HomeESSID, e quindi impostare il nome host su 192.168.1.100?
andato il

@gone Non capisco la domanda. La partita è anche sull'host di destinazione.
Michał Politowski,

1
@typelogic Non facilmente, per quanto ne so. Potresti provare a usare ProxyCommand nc $address ssh, ma poi ad es. tutti i dispositivi hanno la stessa chiave host? Se devi comunque impostare una variabile d'ambiente, non sarà più semplice fornire l'indirizzo a cui collegarti direttamente come argomento ssh?
Michał Politowski l'

5

Se ti capita di avere un nameserver privato al lavoro e se usi lo stesso laptop da ufficio e da casa, puoi trarne vantaggio per ottenere questo:

  1. Modifica il tuo nsswitch.confnel tuo computer per controllare prima il DNS
  2. Crea una voce DNS per gammarisolvere 192.168.1.100 nel tuo DNS privato in ufficio.
  3. Creare una voce nel file / etc / hosts della macchina per risolverla gammaa 55.22.33.99.

In questo modo, quando sei ssh gammain ufficio, si risolverà dal DNS dell'ufficio al 192.168.1.100 e quando ti connetti da casa, si risolverà a 55.22.33.99 dal tuo file hosts.

PS : questa risposta presuppone che non si desidera che gamma disponga di una voce DNS pubblica. Inoltre, se stai eseguendo SSHing sul tuo server da una macchina Windows, penso che dovrebbe esserci un posto equivalente al file nssswitch.conf per sovrascrivere le voci del file hosts.


C'è - è il file hosts. E questo esattamente come lo faccio - quando a casa il mio dominio pubblico si risolve nel mio IP locale. Ottima risposta - è stata anche la prima cosa a cui ho pensato. Bene ... oggi cioè, quando l'ho installato un paio di anni fa, ho dovuto cercare molto su Google per trovare una soluzione.
Mikeserv,

2

Non so se sia possibile farlo, ~/.ssh/configma un altro approccio sarebbe quello di connettersi all'uno o all'altro in base al tuo indirizzo IP esterno. Poiché, presumibilmente, quando sei al lavoro, il tuo IP sarà 55.22.33.NNN, puoi eseguire qualcosa del tipo:

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

Un approccio ancora più semplice è usare il tuo IP interno. Non so come sono configurate le tue due reti, ma se è facile determinare se sei al lavoro o meno attraverso il tuo IP (ad esempio, se hai un IP specifico al lavoro, come 192.168.1.12), puoi farlo ( cambia eth0in qualunque sia il nome della tua scheda di rete):

[[ $(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

Qualunque cosa tu decida di usare, puoi aggiungerla come alias alla tua shell (aggiungi questa linea al file di inizializzazione della tua shell, ~/.bashrcse stai usando bash):

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

Puoi anche trasformarlo in uno script se desideri che altri script possano accedervi (gli alias da .bashrcnon vengono letti durante l'esecuzione di uno script).


2

Non è possibile ottenere questo risultato ~/.ssh/configquando si utilizzano gli indirizzi IP come nomi host. Un'ulteriore complicazione è data dal fatto che non si sta solo connettendo a diversi indirizzi IP ma anche a porte diverse, dal momento che praticamente esclude qualsiasi modifica del risolutore DNS.

Sono corretto - puoi usare la Match originalhost ... exec ...combo in ~/.ssh/config- vedi la risposta di @ MichałPolitowski . Tuttavia, sebbene funzionerà perfettamente per OpenSSH, potresti non trovare necessariamente funzionalità simili in altri client SSH.

È possibile aggirare il problema utilizzando un semplice wrapper (una funzione shell o uno script se è necessario utilizzarlo da varie shell) ssh, che controllerà su quale rete ci si trova e utilizzerà la Hostvoce appropriata . La grande domanda è: come rilevare in modo affidabile su quale rete ti trovi. L'indirizzo IP locale viene in mente, ma non è affidabile, poiché potresti anche connetterti da una LAN che utilizza la stessa sottorete della tua rete di lavoro.

Se puoi avere la stessa porta sia per le reti locali che per quelle remote, puoi modificarle a /etc/resolv.confseconda della rete in cui ti trovi - ovviamente dovrebbe essere fatto automaticamente (molto probabilmente da uno script hook del tuo client DHCP). Oppure - meglio - eseguire il server dei nomi locale (come ad esempio dnsmasq) e fornire la configurazione appropriata. Questo va oltre lo scopo di questa domanda.

Un'altra opzione, se è necessario solo connettersi in modo interattivo, è utilizzare il completamento del comando per la scansione ~/.ssh/config. Ciò ti risparmierebbe un po 'di battitura (specialmente se hai Hostvoci abbastanza variabili ). Qualcosa del genere (per l' bashinizializzazione):

# 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

La prima funzione crea un elenco da cui vengono completati gli host (di solito è sufficiente eseguirlo una volta in ogni shell), il secondo esegue il completamento effettivo, anche se in modo un po 'goffo - completa il nome host solo quando è l'ultimo token sulla riga di comando.

Detto questo, il modo giusto di affrontare questo problema è connettersi alla rete di lavoro tramite una VPN e quindi avere l'indirizzo IP di lavoro locale accessibile come se fossi in ufficio. È quindi possibile hard-wire l'indirizzo in qualunque seconda di quale livello si preferisce: ~/.ssh/config, /etc/resolv.confo (imho migliore opzione) name server dell'ufficio.


Le porte non sono incastonate nella pietra. Potrei sicuramente cambiare la porta SSH locale gammain modo che corrisponda alla porta remota se renderebbe le cose più facili.
IQAndreas,

2

Alcuni anni fa, ho scritto un programma per uno scopo simile. Potrebbe soddisfare le tue esigenze. Con quel programma la configurazione di ssh potrebbe apparire così:

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

1

Un'altra soluzione è utilizzare due diversi file di configurazione per SSH. Potresti considerarlo leggermente meno elegante di avere tutto in un unico file di configurazione, ma è più facile da mantenere.

Si seleziona il file di configurazione che si desidera utilizzare con -F <configfile>.


Grazie. Mi piace l' -Fopzione.
dattiloscritto l'

0

Risposta parziale:

Molte risposte sopra iniziano con "se riesci a rilevare su quale rete ti trovi". Per questo uso uno script che viene eseguito quando le interfacce sono connesse per avviare varie cose (VPN, di solito) quando mi collego a una delle mie solite reti. La tecnica consiste nell'utilizzare ARP per ottenere l'indirizzo MAC del gateway:

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
}

E poi ho una tabella di ricerca per associare la rete al gateway MAC. Naturalmente quella tabella può contenere diversi MAC per la stessa rete (caso tipico sono i vari hotspot WiFi su un grande sito aziendale). Un'altra tabella di ricerca viene utilizzata per determinare lo script da eseguire per quella rete.

Nel mio caso, lo script viene eseguito utilizzando le notifiche desktop Plasma, quindi tutto è in userland.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.