Intereting Posts

Используйте два разных IP-адреса на хост в SSH

У меня есть сервер с именем gamma , постоянно работающий на работе. Иногда я подключаюсь к нему из дома, и в этом случае я использую общедоступный IP-адрес 55.22.33.99 . Иногда я подключаюсь к нему, когда я нахожусь на работе, и вместо того, чтобы отказываться от ненужных пакетов, я подключаюсь через локальный IP-адрес 192.168.1.100 .

На данный момент я разделил их на две разные записи в ~/.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 

Итак, если я на работе, все, что я должен набирать, это ssh gamma-local и я нахожусь; если я дома (или где-либо еще в мире), я запускаю ssh gamma-remote .

При подключении к серверу я предпочитаю не вводить другое имя в зависимости от того, где я, я бы предпочел, чтобы эта часть выполнялась автоматически; например, в некоторых случаях у меня есть автоматические сценарии, которые соединяют тех, кто не знает, где я.

Возникает вопрос, который решает эту проблему, используя сценарий Bash, чтобы сначала «попробовать» подключиться к локальному, а если он не подключен, попробуйте подключиться к удаленному IP-адресу. Это хорошо, но (1) кажется неэффективным (особенно потому, что иногда вам приходится «ждать» для подключения к тайм-ауту, поскольку они не всегда сразу отправляют ошибку), и (2) требует Bash и таскания вокруг скрипта.

Есть ли альтернативный способ достижения этого, который не зависит от использования сценариев Bash, а не «тестирования», чтобы увидеть, работает ли соединение в первую очередь?

Если у вас есть способ узнать, в какой сети вы находитесь, вы можете использовать ключевое слово Match в ~/.ssh/config чтобы делать то, что хотите. Для этого требуется OpenSSH ≥6.5.

Я использую нечто похожее

 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 

Поэтому я использую идентификатор используемой сети wifi для определения того, являюсь ли я дома для целей подключения SSH, но проверять IP-адрес, назначенный вам на компьютере, или что-либо еще, что может различать две сети ,

Если у вас есть частные серверы имен на работе, и если вы используете тот же ноутбук из офиса и дома, вы можете воспользоваться этим для достижения этого:

  1. Измените свой nsswitch.conf на вашем компьютере, чтобы сначала проверить DNS
  2. Создайте запись DNS для gamma чтобы разрешить 192.168.1.100 в вашем частном DNS в офисе.
  3. Создайте запись в файле / etc / hosts вашего компьютера для разрешения gamma до 55.22.33.99.

Таким образом, когда вы получите ssh gamma из офиса, он будет удален из офиса DNS на 192.168.1.100, а когда вы подключитесь из дома, он решит 55.22.33.99 из вашего файла hosts.

PS : Этот ответ предполагает, что вы не хотите, чтобы гамма имела общедоступную запись DNS. Кроме того, если вы используете SSHing на своем сервере с компьютера Windows, я думаю, что должно быть место, эквивалентное файлу nssswitch.conf, чтобы переопределить записи файлов хостов.

Я не знаю, можно ли это сделать через ~/.ssh/config но другой подход состоял бы в том, чтобы подключиться к тому или другому на основе вашего внешнего IP-адреса. Поскольку, по-видимому, когда вы работаете, ваш IP будет 55.22.33.NNN , вы можете запустить что-то вроде:

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

Еще более простой подход – использовать ваш внутренний IP-адрес. Я не знаю, как настроены ваши две сети, но если вам легко определить, работаете ли вы на вашем IP-телефоне или нет, например, если у вас есть определенный IP-адрес на работе, например 192.168.1.12 ), вы может (изменить eth0 на то, что имя вашей сетевой карты):

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

Какой бы вы ни решили использовать, вы можете добавить его как псевдоним в свою оболочку (добавьте эту строку в файл инициализации вашей оболочки, ~/.bashrc если вы используете bash ):

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

Вы также можете сделать это в скрипте, если хотите, чтобы другие скрипты имели к нему доступ (псевдонимы из .bashrc не читаются при запуске скрипта).

Вы не можете достичь этого в ~/.ssh/config при использовании IP-адресов в качестве имен хостов. Дополнительное усложнение объясняется тем фактом, что вы не просто подключаетесь к разным IP-адресам, но также и к различным портам, поскольку это практически исключает любую настройку вашего DNS-преобразователя.

Я стою исправлено – вы можете использовать Match originalhost ... exec ... combo в ~/.ssh/config – см . Ответ @ MichałPolitowski . Однако, хотя это будет отлично работать для OpenSSH, вы, возможно, не обязательно найдете аналогичную функциональность в других SSH-клиентах.

Вы можете обойти проблему, используя простую оболочку (либо функцию оболочки, либо скрипт, если вам нужно использовать ее из разных оболочек) для ssh , которая будет проверять, в какой сети вы находитесь, и использовать соответствующую запись Host . Большой вопрос: как надежно определить, в какой сети вы находитесь. Локальный IP-адрес приходит в голову, но не является надежным, поскольку вы можете также подключаться к локальной сети, использующей ту же подсеть, что и ваша рабочая сеть.

Если вы можете иметь один и тот же порт для локальных и удаленных сетей, вы можете отредактировать свой /etc/resolv.conf зависимости от сети, в которой вы находитесь, – очевидно, это нужно было бы сделать автоматически (скорее всего, из сценария крючка ваш DHCP-клиент). Или – лучше – запустите локальный сервер имен (например, dnsmasq ) и поставьте его с соответствующей конфигурацией. Однако это выходит за рамки этого вопроса.

Другой вариант – если вам нужно только подключиться в интерактивном режиме – это использовать завершение команды, которое сканирует ~/.ssh/config . Это позволит вам немного набирать текст (особенно если у вас достаточно количество записей Host ). Что-то вроде этого (для инициализации bash ):

 # 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 

Первая функция создает список, из которого хосты завершены (обычно этого достаточно, чтобы запускать его один раз в каждой оболочке), второй выполняет фактическое завершение, хотя и немного неуклюжим образом – он только завершает имя хоста, когда он последний токен в командной строке.

Все это говорит о том, что правильный подход к этой проблеме заключается в подключении к рабочей сети через VPN и, таким образом, доступ к локальному рабочему IP-адресу, как если бы вы были в офисе. Затем вы можете жестко связать адрес с любым другим слоем, который вы предпочитаете: ~/.ssh/config , /etc/resolv.conf или (имхо лучший вариант).

Несколько лет назад я написал программу для аналогичной цели. Это может удовлетворить ваши потребности. С этой программой конфигурация ssh может выглядеть так:

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