Warunkowe ProxyCommand w ~ / .ssh / config?

14

Mam ~/.ssh/configskonfigurowane różne hosty, które są dostępne albo w sieci VPN naszej firmy, albo przez serwer proxy SSH.

W tej chwili po prostu mam

Host internal-server
    ProxyCommand ssh -W internal.ip:22 external-server

Jeśli jednak jestem w sieci wewnętrznej, mogę bezpośrednio uzyskać dostęp do wewnętrznego adresu IP, więc proxy przez zewnętrzny serwer tylko opóźnia połączenie.

Czy istnieje sposób, w jaki mogę tymczasowo proxy, jeśli wewnętrzny adres IP nie jest osiągalny, i w inny sposób połączyć się bezpośrednio?

alt
źródło

Odpowiedzi:

8

Zwykle konfiguruję coś takiego. Zakłada, że ​​host pośredni będzie w stanie rozpoznać nazwę.

Host *%homeproxy
    ProxyCommand ssh user@proxyhost /bin/netcat -w 1 $(echo %h | cut -d%% -f1) 22

Więc chciałbym połączyć się z polubieniem ssh blah%homeproxy.

Zoredache
źródło
Moje google-fu mnie zawodzi. Czy możesz to wyjaśnić? Nigdy wcześniej nie widziałem tej składni *%.
fukawi2
3
W tej %postaci nie ma nic specjalnego . Możesz użyć wszystkiego naprawdę. Procent jest używany, ponieważ nie jest prawidłowy w nazwie hosta lub nazwie użytkownika. cutKomenda withing się ProxyCommand używa %jako separatora wyciągnąć hosta.
Zoredache,
1
To dobrze, ale oznacza to, że muszę przeliterować pełną nazwę hosta zamiast aliasu ssh.
alt
@mobiusnz W rzeczywistości oznacza to po prostu, że potrzebujesz innej nazwy dla każdego innego sposobu połączenia. W moim przypadku, na przykład, jeśli jestem w domu, używam ssh targetH, co oznacza cel z domu . Jeśli jest to sieć lokalna, na którą można celować, po prostu ssh target. Byłoby miło, gdyby w odpowiedzi było to bardziej jednoznacznie określone.
Rubens,
4

Używam innej metody przy użyciu dopasowania. W moim przypadku chcę użyć lokalnego serwera proxy, jeśli jest uruchomiony, czy nie, jeśli nie jest. Następująca dyrektywa ładnie to osiąga:

Match Exec "nc -z 127.0.0.1 1086"
    ProxyCommand nc -X 5 -x 127.0.0.1:1086 %h %p

Pasuje do każdej próby ssh i wykonuje szybkie sprawdzenie za pomocą, ncaby sprawdzić, czy mój serwer proxy działa i działa na 1086 (w takim przypadku nckończy się bez błędu). Jeśli tak się stanie, ustawia ProxyCommand.

domoarigato
źródło
2

Dziesięć lat temu napisałem polecenie proxy dla tego rodzaju scenariusza. W twoim przypadku można użyć mojej komendy proxy w następujący sposób:

Host internal-server
    ProxyCommand ssh-multipath-proxy %h:%p -- ssh -W %h:%p external-server

Kilka ostrzeżeń: Jestem trochę zawstydzony przyznając, że nie obsługuje IPv6 i że spróbuje tylko jednego adresu IP na nazwę hosta. Ponadto nie przeniesie banera klienta na serwer przed wysłaniem banera serwera. Ale raczej nie spowoduje to problemów.

kasperd
źródło
2

Dzięki za odpowiedź @ till , bardzo mnie to zainspirowało.

Odkryłem, że możesz siłą przekierować swoje połączenie ProxyCommand nc dst dst-port.

Na przykład połączysz się, B.comjeśli korzystasz

ssh A.com -o ProxyCommand="nc B.com 22"

Ale UserKnownHostsFilenadal będzie nagrywać jakoA.com

Możesz dodać domenę „auto” do swojej ssh_config

Host auto.internal-server
  Hostname {internal-server ip or domain}
  ProxyCommand bash -c '(timeout 0.1 nc -z %h %p) && nc %h %p || ssh -W %h:%p external-server'

Wymieniłem nc -w 1 %h %pz (timeout 0.1 nc -z %h %p) && nc %h %p, to będzie bardziej szybkie, jeśli można dotrzeć do wewnętrznego serwera mniej niż 100ms.

Lub możesz go zastąpić ping, ale może to oznaczać złe informacje, jeśli używasz serwera proxy opartego na TCP proxychainslub serwer nie zezwala na echo ICMP.

Host auto.internal-server
  Hostname {internal-server ip or domain}
  ProxyCommand bash -c '(ping %h &>/dev/null) && nc %h %p || ssh -W %h:%p external-server'

Możesz zastąpić (timeout 0.1 nc -z %h %p)wszystko, co wykrywa, czy jesteś na serwerze wewnętrznym.

Jeśli masz wiele adresów IP kandydatów, nawet Ty możesz użyć tego:

Host auto.internal-server
  Hostname {internal-server ip or domain}
  ProxyCommand bash -c 'f(){(timeout 0.1 ping -c 1 $1 &>/dev/null) && nc $1 %p;}; f 1.1.1.1 || f 2.2.2.2 || f 3.3.3.3'

Spróbuje się połączyć 1.1.1.1, jeśli nie, spróbuj się połączyć 2.2.2.2, a następnie 3.3.3.3.

Komeiji Kuroko
źródło
0

Działa to nieco bardziej automagicznie z niewielkim dodatkowym opóźnieniem 0,1 s:

Host proxyhost.example.com
ProxyCommand none

Host *.example.com
ProxyCommand sh -c "socat 2>/dev/null - tcp4:%h:%p,connect-timeout=0.1 || exec ssh -W  %h:%p proxyhost.example.com"
do
źródło
0

Zwykle tworzyłem inny wpis, taki jak ten -

Host myVM
    ProxyCommand ssh -W internal.ip:22 external-server
    User ubuntu

Host myVM-np
    User ubuntu

Następnie po prostu wywołaj ten, który chcesz, w zależności od bieżącego środowiska proxy.

Sharath Srinivasan
źródło