Como fazer o 'ControlPath' do SSH distinguir entre IPv4 e IPv6?

5

Estou usando

ControlMaster   auto
ControlPath     ~/.ssh/tmp/%l_%r@%h:%p

no meu ~/.ssh/config para abrir várias sessões usando a mesma conexão ao acessar um host via SSH.

Isso funciona bem para a maioria dos casos de uso, mas não permite que eu me conecte ao mesmo nome de host via IPv4 e IPv6 ao mesmo tempo; Todas as conexões adicionais usam o soquete de controle criado pela primeira conexão porque o ControlPath não permite distinguir entre conexões IPv4 e IPv6.

Existe uma maneira de ter soquetes de controle separados para conexões IPv4 e IPv6 (talvez encontrando uma maneira de usar o IP remoto em vez do nome do host remoto no caminho do soquete)?

EDIT # 1

Acabei de me lembrar da opção Match disponível nos arquivos ssh_config e sshd_config e tentei:

Match AddressFamily inet
    ControlPath     ~/.ssh/tmp/%l_%r@%h:%p.inet

Match AddressFamily inet6
    ControlPath     ~/.ssh/tmp/%l_%r@%h:%p.inet6

Infelizmente, isso falha com o " atributo Correspondência não compatível AddressFamily " quando tento conectar-me a qualquer host, então estou de volta à estaca zero…

    
por n.st 16.07.2015 / 20:28

3 respostas

0

Eu dividi minha resposta em duas respostas separadas para que você possa fazer um up / downvote das abordagens "wrapper" e "patch" separadamente.

Solução 1: escreva uma função de wrapper

ssh ()
{
    controlpath=""
    for argument in $@
    do
        if [[ "$argument" = "-"*"4"* ]]
        then
            controlpath="~/.ssh/tmp/%l_%r@%h:%p.inet"
        fi
        if [[ "$argument" = "-"*"6"* ]]
        then
            controlpath="~/.ssh/tmp/%l_%r@%h:%p.inet6"
        fi
    done

    if [ -n "$controlpath" ]
    then
        /usr/bin/ssh -o "ControlPath=$controlpath" $@
    else
        /usr/bin/ssh $@
    fi
}

Esta função de invólucro instruirá ssh a criar soquetes de controle separados para ssh host , ssh -4 host e ssh -6 host .
Ele pode não analisar algo como ssh -464466 host corretamente (mesmo que isso seja tecnicamente permitido), mas deve ser a solução mais fácil para cenários simples.

    
por 25.07.2015 / 13:34
2

Este não é um caso de uso típico, portanto, não há uma maneira direta de fazer isso. Mas, você pode solucionar isso usando o arquivo de configuração do usuário, se não precisar de muitos hosts remotos:

Host hostname-4
    Hostname hostname
    AddressFamily inet
    ControlPath ~/.ssh/master4-%l%h%p%r
Host hostname-6
    Hostname hostname
    AddressFamily inet6
    ControlPath ~/.ssh/master6-%l%h%p%r
    
por 16.07.2015 / 22:33
0

Eu dividi minha resposta em duas respostas separadas para que você possa fazer um up / downvote das abordagens "wrapper" e "patch" separadamente.

Solução 2: Use a fonte, Luke!

Como mencionei na atualização da minha resposta, o OpenSSH não suporta Match AddressFamily - ainda .
É bastante fácil adicionar uma cláusula correspondente à Match parsing em readconf.c . Meu patch de prova de conceito funcionou, mas envolveu um monte de strings codificadas, então certamente precisa de mais algum trabalho antes de poder submetê-lo aos mantenedores do OpenSSH para consideração.

Também pode valer a pena conferir se não pudermos adicionar outro marcador (como %a ) para ControlPath definições que seriam avaliadas como any , inet ou inet6 , dependendo na família de endereços usada.
No entanto, isso causará problemas dependendo da ordem em que as opções AddressFamily e ControlPath são avaliadas e armazenadas, portanto, talvez seja necessário que algumas alterações bastante extensas funcionem. O mesmo problema se aplica à minha ideia original de expandir o espaço reservado para a família de endereços real usada para a conexão: A família de endereços depende de uma chamada gethostbyname() que nem sequer é feita quando existe um soquete de controle adequado.

    
por 25.07.2015 / 13:34

Tags