Use dois endereços IP diferentes por host no SSH

22

Eu tenho um servidor chamado gamma , constantemente em funcionamento no trabalho. Às vezes, eu me conecto a ele em casa, caso em que uso o endereço IP público 55.22.33.99 . Às vezes, conecto-me a ele quando estou no trabalho e, em vez de devolver meus pacotes desnecessariamente, conecto-me por meio do endereço IP local, 192.168.1.100 .

No momento, eu os divido em duas entradas diferentes em ~/.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

Então, se eu estou no trabalho, tudo que eu tenho que digitar é ssh gamma-local e eu estou dentro; se estou em casa (ou em qualquer outro lugar do mundo), corro ssh gamma-remote .

Ao conectar-se ao servidor, prefiro não ter que digitar um nome diferente, dependendo de onde estou, prefiro que essa parte seja feita automaticamente; Por exemplo, em alguns casos, tenho scripts automatizados que conectam quem não sabe onde estou.

Existe uma pergunta que resolve esse problema usando um script Bash para "tentar" se conectar ao primeiro local, e se ele não se conectar, tente se conectar ao endereço IP remoto. Isso é bom, mas (1) parece ineficiente (especialmente porque às vezes você tem que "esperar" por conexões para o tempo limite, pois elas nem sempre enviam um erro de volta imediatamente) e (2) requer Bash e lugging pelo script. / p>

Existe uma maneira alternativa de conseguir isso que não depende do uso de scripts Bash, nem "testar" para ver se a conexão funciona primeiro?

    
por IQAndreas 22.12.2014 / 10:28

7 respostas

28

Se você tem uma maneira de reconhecer em qual rede você está, então você pode usar a palavra-chave Match em ~/.ssh/config para fazer o que você deseja. Isso requer OpenSSH ≥6,5.

Eu uso algo parecido com

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

Estou usando o identificador da rede Wi-Fi usada para decidir se estou em casa com a finalidade da conexão SSH, mas verificar o endereço IP atribuído ao seu computador ou qualquer outra coisa que diferencie as duas redes pode ser usado também.

    
por 22.12.2014 / 13:09
5

Se você tiver servidores de nomes privados no trabalho e usar o mesmo laptop do escritório e de casa, aproveite para conseguir isso:

  1. Modifique seu nsswitch.conf em sua máquina para verificar primeiro o DNS
  2. Crie uma entrada de DNS para gamma para resolver para 192.168.1.100 em seu DNS privado no escritório.
  3. Crie uma entrada no arquivo / etc / hosts da sua máquina para resolver gamma para 55.22.33.99.

Desta forma, quando você ssh gamma do escritório, ele irá resolver do DNS do escritório para o 192.168.1.100 e quando você se conectar de casa, ele irá resolver para 55.22.33.99 do seu arquivo de hosts.

P.S : Esta resposta assume que você não deseja que o gama tenha uma entrada de DNS público. Além disso, se você estiver usando o SSH em seu servidor a partir de uma máquina Windows, acho que deve haver algum lugar equivalente ao arquivo nssswitch.conf para substituir as entradas do arquivo de hosts.

    
por 22.12.2014 / 13:03
2

Não sei se é possível fazer isso através de ~/.ssh/config , mas outra abordagem seria conectar-se a um ou outro com base em seu endereço IP externo. Como, presumivelmente, quando você está no trabalho, seu IP será 55.22.33.NNN , você pode executar algo como:

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

Uma abordagem ainda mais simples é usar o seu IP interno. Não sei como suas duas redes estão configuradas, mas se é fácil determinar se você está no trabalho ou não através do seu IP (por exemplo, se você tem um IP específico no trabalho, como 192.168.1.12 ), pode fazer (altere eth0 para qualquer nome da sua placa de rede):

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

Qualquer que você decida usar, você pode adicioná-lo como um alias ao seu shell (adicione esta linha ao arquivo de inicialização do seu shell, ~/.bashrc se você estiver 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

Você também pode transformar isso em um script se quiser que outros scripts tenham acesso a ele (os aliases de .bashrc não são lidos ao executar um script).

    
por 22.12.2014 / 11:07
2

Você não pode conseguir isso em ~/.ssh/config ao usar endereços IP como nomes de host. Uma complicação adicional é introduzida pelo fato de que você não está apenas se conectando a endereços IP diferentes, mas também a portas diferentes, já que isso praticamente impede qualquer ajuste no seu resolvedor de DNS.

Eu corrijo - você pode usar a combinação Match originalhost ... exec ... em ~/.ssh/config - veja resposta do @ MichałPolitowski . No entanto, embora funcione perfeitamente para o OpenSSH, você pode não necessariamente encontrar uma funcionalidade semelhante em outros clientes SSH.

Você pode contornar o problema usando um invólucro simples (uma função de shell ou um script, se precisar usá-lo de vários shells) para ssh , que verificará em qual rede você está e usará o% co_de apropriado. % de entrada. A grande questão é como detectar de forma confiável em que rede você está. O endereço IP local vem à mente, mas não é confiável, pois você também pode se conectar a partir de uma LAN que usa a mesma sub-rede de sua rede de trabalho.

Se você pode ter a mesma porta para redes locais e remotas, você pode editar seu Host dependendo da rede em que estiver - obviamente teria que ser feito automaticamente (provavelmente a partir de um script de gancho de seu cliente DHCP). Ou - melhor - execute o servidor de nomes local (por exemplo, /etc/resolv.conf ) e forneça a configuração apropriada. Isso vai além do escopo desta questão.

Outra opção - se você só precisa se conectar de forma interativa - é usar a conclusão de comando que faria a varredura de dnsmasq . Isso pouparia um pouco de digitação (especialmente se você tiver variados o suficiente em ~/.ssh/config entradas). Algo parecido com isto (para Host initialisation):

# 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

A primeira função cria uma lista a partir da qual os hosts são concluídos (geralmente é suficiente para executá-la uma vez em cada shell), o segundo realiza a conclusão real, embora de forma um pouco desajeitada - só completa o nome do host quando é o último token na linha de comando.

Tudo isso dito, o caminho certo para abordar este problema é conectar-se à rede de trabalho através de uma VPN e, portanto, ter o endereço IP local de trabalho acessível como se você estivesse no escritório. Você pode vincular o endereço em qualquer camada que preferir: bash , ~/.ssh/config ou (melhor opção) servidor de nomes do escritório.

    
por 22.12.2014 / 11:08
2

Alguns anos atrás, eu escrevi um programa para uma propósito similar. Pode atender às suas necessidades. Com esse programa, a configuração do ssh poderia ser assim:

Host gamma
    ProxyCommand ssh-multipath-proxy 192.168.1.100:22 55.22.33.99:12345
    User andreas
    
por 22.12.2014 / 19:22
1

Ainda outra solução é usar dois arquivos de configuração diferentes para o SSH. Você pode considerar isso um pouco menos elegante do que ter tudo em um arquivo de configuração, mas é mais fácil de manter.

Você seleciona o arquivo de configuração que deseja usar com -F <configfile> .

    
por 29.11.2017 / 21:30
0

Resposta parcial:

Muitas respostas acima começam com "se você puder detectar em qual rede você está". Para isso eu uso um script que é executado quando as interfaces são conectadas para iniciar várias coisas (VPNs, geralmente) quando eu me conecto a uma das minhas redes habituais. A técnica é usar o ARP para obter o endereço MAC do 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 então eu tenho uma tabela de pesquisa para associar a rede ao MAC do gateway. Claro que essa tabela pode conter vários MAC para a mesma rede (caso típico é os vários pontos de acesso Wi-Fi em um grande site corporativo). Outra tabela de consulta é usada para determinar o script a ser executado para essa rede.

No meu caso, o script é executado usando as notificações da área de trabalho do Plasma, portanto, tudo está na userland.

    
por 29.11.2017 / 22:54

Tags