Назад | Перейти на главную страницу

Динамическое перенаправление портов на основе имени хоста или исходного IP-адреса

Я программист, пытающийся понять некоторые вещи за пределами моей области:

Скажем, у меня есть одна машина, и клиенты будут подключаться к ней по протоколу TCP (но не по протоколу http!). Я хочу перенаправить клиентов на их собственные порты в зависимости от имени хоста, к которому они подключаются. Например, client1 подключается к client1.myserver.com и к порту 1234. client2.myserver.com -> 1235, client3.myserver.com -> 1236 и т. Д.

Я хочу динамически контролировать, как порты x, поскольку хост y фактически указывает на порт z на моей физической машине.

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

Если бы я хотел написать такой уровень сам (поскольку он может быть немного специфичным для приложения), можно ли это сделать в java или node.js (я имею в виду, можно ли это сделать с помощью API более высокого уровня, или мне нужно начать разбирать ip пакеты)? Как мне узнать, к какому имени хоста подключился клиент, поскольку все имена хостов относятся к одному и тому же компьютеру?

Я также буду признателен за указатели на любой материал для чтения.

На уровне IP не существует такого понятия, как имя хоста. Имя хоста - это абстракция IP-адреса на уровне приложения, и на уровне Интернета или транспорта они не имеют значения.

В общем хостинге HTTP этот трюк абстрагируется в процессе обработки HTTP разговор, который случается после диалог TCP запущен. Именно по этой причине для запуска SSL-сервера требовался выделенный IP-адрес до тех пор, пока SSL-диалог происходит раньше, чем HTTP (с тех пор это было исправлено в новых версиях TLS, где HOSTNAME теперь может быть включен как часть согласования SSL. ).

Для экземпляра HTTP с общим хостингом протоколы согласовываются примерно в таком порядке:

TCP -> SSL -> HTTP

Каждый протокол не может быть запущен, пока не будут завершены предыдущие. До недавнего времени только последний шаг в цепочке знал имена хостов, поэтому программное обеспечение веб-сервера должно было обрабатывать сопоставление имен хостов с IP по принципу «многие к одному».

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

Точные необходимые шаги зависят от самого протокола приложения. Некоторые, например HTTP, включают заголовок HOSTNAME, указывающий имя хоста, с которым клиент ожидает разговаривать. Другие, например некоторые протоколы Microsoft, используют записи SRV на основе DNS для определения точного IP-адреса. и комбинация портов. Поскольку похоже, что вы разрабатываете свой собственный протокол приложения с нуля, я бы посоветовал последовать примеру HTTP и включить заголовок HOSTNAME на начальных этапах согласования протокола.

Проще всего этого добиться, используя записи SRV в DNS:

http://en.wikipedia.org/wiki/SRV_record

Можете ли вы более четко описать, что вы пытаетесь сделать и почему? «Почему» очень поможет. Какие клиенты? Какой протокол?

Есть много способов сделать это на основе протоколов и потоков данных.

Рассмотрим внедрение pf, iptables или ebtables, примеры см. В «черном списке ssh». Посмотрите на LVS, HAproxy и другие балансировщики нагрузки для общего перенаправления.

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

  • SSH в один открытый порт (поддержка терминала не требуется)
  • войдите в систему как userX (желательно с помощью ключей), это запускает сценарий, который запускает другой экземпляр сервера на порту XXXXX и отвечает клиенту с новым номером порта
  • Сообщение "порт XXXXX открыт" передается обратно клиенту, начальный сеанс ssh закрывается
  • клиент или клиентское приложение затем повторно подключается, используя теперь открытый порт XXXXX
  • когда клиент отключает альтернативный экземпляр, порт XXXXX закрыт и / или порт XXXXX закрыт.

Определенные порты могут быть назначены на основе ключей / пользователей, обратного просмотра, передачи сообщений и т. Д. Некоторые просто оставляют экземпляры работающими и открываются / закрываются с помощью внедрения брандмауэра pf / iptables. Другие расширяют это, используя правило брандмауэра, чтобы инициировать запуск службы и не запускать начальный SSH (или другую службу) до тех пор, пока на указанный порт не будет отправлен пинг с определенным типом пакета. Я предпочитаю «недавно согласованное» настраиваемое правило брандмауэра для блокировки случайных пакетов и остановки / запуска экземпляров сервера для менее динамического взаимодействия с брандмауэром.

Эта идея может работать с любым протоколом и сервисом, который можно закодировать или написать сценарий.

Материалы для чтения по сети TCP / IP: все, что написано или рекомендовано У. Ричардом Стивенсом. http://www.kohala.com/start/

Не сбрасывайте со счетов использование SSH-туннелей в качестве временной меры в процессе разработки. Они могут достичь всего, что вам нужно, без кода. Какое у вас приложение? Разве это не должно быть безопасным общением? Как вы собираетесь занести в черный список скриптовых хакеров? Это больше вам придется писать и отлаживать. В любом случае вы должны разделять свой код на части, поэтому разрабатывайте все остальное, используя SSH в качестве транспорта, перенаправления портов, шифрования, ведения журнала использования, внесения в черный список и т. Д. Затем, когда все остальное будет сделано, напишите свой собственный механизм сетевого протокола для замены SSH. Нет необходимости в терминальном доступе для пользователей на SSH-сервере шлюза для использования туннелей.