SSH доступ изнутри и снаружи локальной сети с использованием одной и той же команды терминала


10

У меня есть Raspberry Pi (RPi), и я делаю удаленные подключения к нему с помощью ssh. Мне удалось правильно настроить ssh, чтобы я мог получить доступ к RPi как из локальной сети, так и из Интернета (используя определенный порт, который я открыл на своем маршрутизаторе).

Предполагая имя пользователя johnи RPi с именем raspi:

Доступ к локальной сети

ssh john@192.168.2.7
ssh john@raspi
ssh raspi

Внешний доступ к локальной сети

ssh -p 1234 john@12.345.67.89
ssh -p 1234 12.345.67.89

Но как я могу просто сделать это ssh raspiза пределами моей локальной сети? Есть ли способ настроить raspi, чтобы он указывал на два IP-адреса, один в локальной сети, а другой через интернет?

Что я в основном хочу, так это получить доступ к своему RPi в одиночку, независимо от того, нахожусь ли я дома или на работе.


Вы можете запустить DNS-сервер в локальной сети, который отвечает на запрос имени «raspi» с локальным IP-адресом локальной сети. Теперь преобразование этого же имени в другой внешний адрес потребовало бы, чтобы имя было заполнено (динамический DNS) таким образом, чтобы оно также разрешалось. Но вам, вероятно, понадобится более длинное имя, чем "raspi".
ChuckCottrill

Смотрите этот Q & A: unix.stackexchange.com/questions/61655/...
ОДС

Ответы:


7

Если присмотреться к вашему вопросу, кажется, вы используете один и тот же компьютер как внутри, так и за пределами локальной сети. Я изменил свой ответ соответственно:

В вашем ~/.ssh/config, добавьте:

Host raspi-wan
    HostName 12.34.56.78
    User john
    Port 1234

Host raspi-lan
    HostName 192.168.1.2
    User john
    Port 22

Затем вы можете ssh raspi-wanизвне ЛВС или ssh raspi-lanизнутри ЛВС, не обращаясь к DNS-серверам и не редактируя /etc/hostsдля всех пользователей, и даже не делая никаких действий в качестве пользователя root. Если вы хотите, чтобы имя raspiразрешалось по-разному, в зависимости от того, где вы находитесь, это, вероятно, потребует некоторой магии сценариев оболочки для обнаружения вашей сети и принятия соответствующих мер.


1
Спасибо DopeGhoti, мне очень удобно, чтобы ваше решение включало в себя -wanи -lanпостфикс. Мой SSH, однако, не понравился Usernameполе (плохой вариант конфигурации). Без него работает нормально.
Aeronaelius

2
Извините, правильный синтаксис есть User john, нет UserName. Я исправляю свой ответ, чтобы отразить это, и как только вы таким образом настроили свой конфиг, вы можете опустить имя пользователя из sshкомандной строки.
DopeGhoti

5

Это вполне выполнимо только с помощью конфигурации ssh, без необходимости использовать отдельные псевдонимы для lan и wan или создания дополнительных портов для переадресации. (Но вам, естественно, нужен какой-то способ определить, находитесь ли вы внутри локальной сети или нет)

В ~/.ssh/config, вы хотите добавить что-то вроде этого:

Match host raspi exec "am_i_outside_of_my_lan"
    HostName 12.345.67.89
    Port 1234

Вместо этого am_i_outside_of_my_lanвы захотите разместить команду, которая определяет, находитесь ли вы в своей домашней сети или нет, и возвращает с 0 кодом выхода, если вы находитесь за ее пределами, и что-то еще в противном случае.

hostУсловие, вероятно , само за себя, но execсостояние требует некоторого объяснения: Это соответствует только тогда , когда данная команда возвращается с кодом выхода 0, то есть. Нет ошибки.

Другими словами, эта host raspiчасть ограничивает это правило, когда вы пытаетесь подключиться к хосту raspi, и exec "am_i_outside_my_lan"еще больше ограничивает его, чтобы оно применялось только при подключении извне вашей домашней сети. Таким образом, внутри вашей домашней сети ssh user@raspiпроисходит именно то, что обычно, но вне этого правила совпадают, и вместо этого это эквивалентно ssh -p 1234 user@12.345.67.89.

Что касается того, что использовать вместо этого am_i_outside_of_my_lan, это полностью зависит от вашей настройки. Я предлагаю размещать команды в отдельном скрипте вместо того, чтобы пытаться писать их в строке, потому что цитата кажется немного трудной для понимания.

Лично я использовал следующий скрипт на Python, чтобы определить, нахожусь ли я в своей собственной сети: (Поскольку мое доменное имя преобразуется в локальный ip внутри моей собственной сети)

#! /usr/bin/env python
import socket, sys

sys.exit(socket.gethostbyname('mydomain.com').startswith('192.168.1.'))

Если у вас нет аналогичной настройки, возможно, вам придется заняться чем-то другим. (Например, вы можете посмотреть имя беспроводной сети, к которой вы подключены, или даже запросить какой-нибудь сервис what-is-my-ip, чтобы получить внешний ip сети, к которой вы подключены)


Это правильный ответ; очень грустно, что у других есть больше голосов.
Джонатан Томер

@JonathanTomer: Честно говоря, я ответил на это через 3 года после того, как его спросили, тогда как ответы с более высокой оценкой были опубликованы в течение нескольких часов, так что это всего лишь случай «ранняя пташка получает червя»: P (у меня также есть сказать, что мне очень нравится конкретный вариант этого общего решения Эллиса Хога - использование arp довольно умно и делает решение более универсальным, так как команда обнаружения сети не должна настраиваться для каждой настройки сети)
Алекси Торхамо

3

На вашем компьютере (замыкающийся ИНГ один), вы можете установить имя хоста 12.345.67.89. Откройте свой /etc/hostsфайл и установите запись DNS:

12.345.67.89    raspi

Ваша машина преобразует «raspi» в «12.345.67.89» как часть процесса локального разрешения DNS. Если вы используете несколько машин, изменения должны быть сделаны на каждом из них. Проблема в том, что для редактирования требуется доступ с правами суперпользователя /etc/hosts, и он может быть не везде.

Если вы хотите, чтобы «распи» автоматически распознавался из любого места, то извините: невозможно. Это потребует регистрации «raspi» в качестве доменного имени, что не может произойти, поскольку «raspi» не имеет TLD и не зависит от корневого сервера DNS. Тем не менее, вы можете зарегистрировать доменное имя (скажем cfbaptista.me, и указать его на свой IP-адрес в глобальной сети. С некоторой переадресацией портов вы сможете получить доступ к вашему Raspberry Pi с помощью:

ssh (you@)(raspi.)cfbaptista.me

(тем не менее, это тратит деньги почти даром ...)

Что касается user@части, это зависит от вашего логина на разных машинах. Если у вас есть такое же имя на соединительном машине и на пульте один, то нет необходимости указывать. Если нет, вам нужно указать, кто вы на удаленной машине.


примечание: как уже упоминалось в другом ответе, вы можете создать псевдонимы хоста в вашей конфигурации SSH, которая, конечно, не требует root.
Струджи

В самом деле ! Вот небольшая ссылка: коллективныйidea.com
blog/

0

Цель: ssh raspi должна работать внутри локальной сети и в общедоступном Интернете.

Для этого необходимо убедиться, что имя соответствует внутреннему IP-адресу локальной сети и общедоступному IP-адресу извне.

Во-первых, вы должны получить доменное имя, например raspi.yourdomain.com. Посетите http://freedns.afraid.org/ для бесплатных доменов для хобби. Укажите домен на ваш публичный IP

Для локальной сети я рекомендую запустить DNSMasq. Открытая прошивка DD-WRT тесно интегрируется с DNSMasq, используя ее для DHCP и DNS. Вам просто нужно указать свой поисковый домен («yourdomain.com»), и он будет автоматически назначать DNS-имена на основе запрошенного имени каждого клиента. Чтобы это работало, нужно прочитать / raspi / etc / hostname raspi.

После этого raspi.yourdomain.com должен разрешить локальный IP-адрес в вашей локальной сети (просто убедитесь, что вы используете локальный DNS на всех своих машинах).

Теперь вы, вероятно, не хотите открывать порт 22 общедоступному Интернету, потому что вы получите тонну перехвата трафика. Таким образом, ваш маршрутизатор может отображать raspi: 22 как некоторый другой порт, скажем, 1234. Чтобы использовать один и тот же порт как в общедоступных, так и во внутренних сетях, вы можете добавить правило перенаправления портов в raspi. В Linux:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1234 -j REDIRECT --to-port 22
sudo sh -c 'iptables-save > /etc/iptables/iptables.rules'

(измените eth0 на имя вашего сетевого интерфейса, как показано ip linkили ifconfig, и 1234 на ваш публичный порт)

Теперь вы можете ssh -p 1234 raspi.yourdomain.comкак из публичной сети, так и из локальной сети.

Вы можете добавить запись в ~ / .ssh / config на своем клиентском компьютере, чтобы сократить это до всего ssh raspi, как упомянуто @DopeGhoti.

Если вы хотите выставить SSH-порты дополнительных машин на одном и том же общедоступном IP-адресе, просто повторите процесс с другим DNS-именем и публичным портом. Ура!


0

Вот краткая, рабочая версия ответа Алекси Торхамо, использующая curl, чтобы получить ваш текущий публичный ip, а затем проверить, соответствует ли он общедоступному ip вашего сервера (то есть вы находитесь в той же локальной сети).

В вашем ~/.ssh/configдобавлении

Match host raspi exec "[[ $(curl -s ipinfo.io/ip) == '12.345.67.89' ]]"
  User john
  HostName 192.168.2.7

Match host raspi exec "[[ $(curl -s ipinfo.io/ip) != '12.345.67.89' ]]"
  User john
  HostName 12.345.67.89
  Port 1234

Я полагаю, ssh что все соответствующие директивы будут обрабатываться по порядку, поэтому в теории вы должны быть в состоянии сделать что-то вроде « Match host raspi / User john / HostName 192.168.2.7после» Match host raspi exec "[[ $(curl -s ipinfo.io/ip) != '12.345.67.89' ]]" / HostName 12.345.67.89 / Port 1234и получить тот же эффект только с одним curlвызовом, позволяя == '12.345.67.89'прецеденту быть принятым из-за сбоя второго Matchправила exec.
февраля

(Вам просто нужно убедиться, что каждый аргумент, указанный в первом Match, либо совпадает, либо также указан во втором - если вы указали нестандартный Port xxxxв первом Matchи хотите использовать стандартный порт во втором Match, вам придется явно переопределить его обратно, Port 22чтобы он не продолжал использовать порт xxxx.)
FeRD

0

Предполагая, что ваш компьютер имеет IP 192.168.1. * При подключении к локальной сети, вы можете добиться этого с помощью следующей конфигурации, ~/.ssh/configчтобы вы всегда могли использовать одну и ту же команду (просто ssh raspi) для подключения:

Match Originalhost raspi Exec "ifconfig | grep 192\.168\.1\."
    HostName 192.168.1.2
    User john
    Port 22

Host raspi
    HostName 12.34.56.78
    User john
    Port 1234

0

Это решение предполагает, что в вашей домашней сети есть один маршрутизатор, который, как я считаю, является распространенным случаем.

Добавьте к вашему ~/.ssh/config

Match host raspi exec "test $(arp 192.168.1.1 | awk '{print $4}') = ROUTER_MAC_ADDRESS"
        Hostname 192.168.2.7
        User john

Host raspi
        Hostname 12.345.67.89
        Port 1234
        User john
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.