Hatred's Log Place

DON'T PANIC!

Dec 24, 2020 - 4 minute read - Linux Programming

HOSTALIASES for IP

Время от времени возникает необходимость организовать аналог /etc/hosts, но индивидуально для пользователя. Такая возможность есть, и называется HOSTALIASES.

HOSTALIASES

Более подробно про него можно почитать в hostname(7).

Трюк будет работать только если удовлетворяются два условия для работы программы:

  1. используется getaddrinfo(3) или gethostbyname(3) для резолвинга имён;

  2. не установлен SETUID бит для запуска с правами другого пользователя. Для таких программ glibc чистит некоторые переменные окружения в том числе и HOSTALIASES.

Второе условия интересное, к примеру ping имеет установленный setuid бит для пользователя root, поэтому хосты, описанные через HOSTALIASES с ним работать не будут.

Ещё один нюанс кроется в самом названии переменной окружения - HOST ALIASES, или “синонимы хостов”. Т.е. это не прямая замена /etc/hosts, это синонимы для уже существующих хостов. И слово “хост” здесь имеет ключевое значение: IP адрес указываться не может.

Приехали…

Но в наш век тотального интернета на любой чих уже придуман свой сервис. Логика простая: если мы не можем указать IP, то мы должны указать доменное имя, да такое, что бы оно раскрылось в нужный нам IP.

И тут мы приветствуем сервис xip.io. xip.io больше не встречаем, больше не доступен. На замену ему:

  • nip.io - drop-in-place замена. Заменяем x на n :-)
  • sslip.io - так же drop-in-place замена.

С ним всё очень просто: скрываем IP адрес в виде под-домена и весь этот под-домен резолвится в нужный нам адрес. Трудно для восприятия? Поэтому вот простой пример:

$ host 192.168.0.100.nip.io
192.168.0.100.nip.io has address 192.168.0.100

На сайте приведены и другие форматы имени, можете поиграться с любыми.

Итак, теперь если мы хотим записать наш алиас для имени, допустим dev_local, с реальным IP адресом 192.168.0.100, то нужно произвести примерно следующее:

echo 'dev_local 192.168.0.100.nip.io' >> ~/.hosts
export HOSTALIASES=~/.hosts

Последнюю строчку можно добавить в стартовые скрипты, что бы не вводить каждый раз. После чего можно запустить, допустим, Firefox:

firefox dev_local

Вуаля!

SSH, удалённая отладка и все все все

Теперь вопрос, а для чего это может пригодится?

У меня, как обычно, возникла необходимость удалённой отладки ( в этот раз не сильно) через Qt Creator. Для доступа к устройству используется SSH, но с достаточно хитрой конфигурацией, все параметры которой нельзя передать через диалог настройки устройства в QtC. Да и доступ этот нужен через консоль, для того же ssh, scp. Я всегда такие хитрые настройки выношу в ~/.ssh/config, создавая короткий алиас, вроде упомянутого выше dev_local.

В диалоге настройки QtC для Generic Linux Device можно указывать короткое SSH имя и SSH часть это прекрасно поймёт, но как только дойдёт время до запуска отладчика, то ничего путнего вы не получите: тот же самый синоним используется как имя хоста для подключения к gdb-server на удалённом хосте, про который система разрешения доменных имён понятия не имеет.

Вот тут нам и поможет трюк с HOSTALISES. То есть, у нас теперь есть SSH конфигурация с именем dev_local в ~/.ssh/config и запись:

dev_local 192.168.0.100.nip.io

в ~/.hosts, после чего удалённая отладка волшебным образом начинает работать в QtC.

Более сложный вариант

Для более сложного варианта не нужен трюк с сервисами типа xip.io/nip.io, но всё же.

Итак, теперь у меня машина не в локальной сети, а в удалённой. Да ещё доступ через “бастион” - это сервер, который торчит наружу и пробрасывает ssh подключения, при этом сам ssh подключения не устанавливает, но ключи проверяет. По сути, аналог таких действий:

  1. подключиться к внешнему хосту;

  2. с него подключиться к внутреннему хосту.

Конфигурация ssh для такого подключения может выглядеть так:

Host bastion
        Port 2222
        User tunnel
        Hostname bastion.company.com
        IdentityFile ~/.ssh/id_rsa-company
        IdentitiesOnly yes


Host dev_remote
        User root
        Hostname 192.168.1.200
        IdentityFile ~/.ssh/id_rsa-company
        ProxyCommand ssh bastion -W %h:%p

Здесь хоть и наворочено, но при детальном разборе всё достаточно просто и логично. Для подключения достаточно набрать:

ssh dev_remote

Вопрос: а что записать в ~/.hosts? Ответ простой:

dev_remote localhost

Но понятным он от этого не становится :) Дело в том, что достучаться по IP, без VPN (можно поднять SSH VPN) к dev_remote мы ни при каких условиях не сможем, поэтому, самый простой способ, это использовать тот же самый SSH и пробросить отладочный порт gdb-server на localhost и направлять gdb на него.

И именно тут кроется небольшое ограничение: в настройках QtC для устройства нужно указать ОДИН отладочный порт (Free Ports в настройках Generic Linux Device в QtC) и именно его пробросить (номер порта локального и удалённого должны быть идентичны):

ssh -L 10000:localhost:100000 dev_remote

Команду нужно запускать заново после перезагрузки удалённой машины.

Устройство в локальной сети, но нет интернета

Или нет доступа к сервисам xip.io/nip.io (с роскомпозором станется).

Тут, как обычно, варианта два:

  1. самый правильный, по мне: настроить mdns и обращаться к удалённой машине по имени somehostname.local, его же прописать в ~/.hosts;

  2. или использовать тот же подход, что и для удалённого сервера, с алиасом на localhost и пробросом порта вручную.

Вместо заключения

В копилку возможностей удалённой отладки прибыло. Доступ через “бастион” можно расширить, когда совсем ничего нет, сеть, допустим, домашняя, нет белого IP, пусть даже динамического, но есть возможность запустить Any Desk. Да, пусть это закрытое коммерческое решение, но оно позволяет пробрасывать порты. А этого уже достаточно для организации SSH доступа на удалённую машину и запуска отладки.