Маршрутизация трафика SSH на основе домена с HAProxy
В настоящее время я строю свой собственный небольшой кластер дома и пытаюсь заставить SSH-маршрутизацию (балансировку нагрузки) работать с HAProxy. Я понял, как маршрутизировать HTTP-трафик, но я борюсь с SSH. Я не знаю достаточно о протоколе TCP, чтобы сразу узнать, что мне нужно искать, чтобы я мог определить, как запрашивать соединения для чего-то вроде хоста (не уверен, что это вообще где-то в соединении) или просто что-то, что идентифицирует какой сервер я хочу в SSH.
В документации снова и снова упоминается трафик SSH, поэтому я мог что-то пропустить. Я не хочу использовать разные порты и маршрутизировать туда и обратно, используя разные порты, потому что они могут быть нестандартными, поэтому заблокированы в общедоступных сетях или других вещах, которые ограничивают меня.
Моя текущая настройка выглядит так:
Запрос на мои домены (или IP) -> Маршрутизатор -> Переадресация NAT в зависимости от порта -> HAProxy, прослушивающий этот порт -> теперь должен идентифицировать трафик, выделенный для определенного сервера, и трафик прокси к нему.
Редактировать: Поскольку Cha0s прояснилось, это просто невозможно с SSH (или так).
Если вас интересует другой метод, ответ Свена дает хорошее представление о том, как сделать что-то похожее, но при этом разные субдомены разрешают разные публичные статические IP-адреса.
3 ответа
Я считаю, что вы смешиваете условия.
Балансировка нагрузки обычно означает, что вы подключаетесь к одному хосту (example.com
) и позволить распределителю нагрузки распределить все подключения к одному или нескольким хостам бэкэнда, обычно без контроля пользователя, к какому фактическому хосту вы подключаетесь. Это легко сделать для SSH различными способами.
Некоторые протоколы, такие как HTTP с Host
заголовок, может дать балансировщику нагрузки больше информации, чтобы решить, на какие внутренние серверы должно быть направлено соединение (например, example.com
направляется в a
а также b
, в то время как example.org
направляется в c
а также d
).
У SSH нет такого поля, и, следовательно, это невозможно сделать с помощью балансировщика нагрузки и только одного IP-адреса. Это делает LB непригодным для этой задачи.
Как правило, это решается путем использования хоста в качестве хоста прокси / шлюза / перехода SSH и инструктирует ваших клиентов SSH использовать его как таковой. Если вы используете OpenSSH, поместите следующее в ваших клиентов ~/.ssh/config
Host *.internal.lan
ProxyCommand ssh -q -A -x proxy.example.com -W %h:%p
Теперь, если вы подключитесь к именам, перечисленным в Host
линия, ваш клиент SSH сначала подключится к proxy.example.com
(который должен указывать на ваш общедоступный IP-адрес) и использовать его в качестве шлюза для пересылки на фактическую машину (используйте переадресацию порта NAT на порт 22 фактической прокси-машины, если это применимо). Обратите внимание, что proxy.example.com
должен быть в состоянии решить *.internal.lan
, Либо настройте DNS-сервер, либо используйте внутренний, предлагаемый вашим маршрутизатором, для достижения этой цели.
После этого из внешней сети вы подключаетесь к nas.internal.lan
чтобы добраться до вашего NAS (или raspi.internal.lan
и т. д.), а внутри вашей локальной сети вы просто используете nas
или же raspi
(поэтому соединение прямое, а не через шлюз).
Другой способ, учитывая тот факт, что вы используете NAT:
Создайте переадресацию портов в вашем маршрутизаторе NAT, например, как
Port 2210 -> internal host1, port 22
Port 2211 -> internal host2, port 22
и затем поместите следующее в ваших клиентов ~/.ssh/config
:
Host host1.example.com
Port 2210
Host host2.example.com
Port 2211
и убедитесь, host1/2.example.com
оба указывают на ваш внешний IP-адрес.
Тогда вы можете просто подключиться через SSH к host1.example.com
и OpenSSH подключится к порту 2210, который пересылается на ваш внутренний хост1 шлюзом NAT.
Оба метода работают в вашем сценарии.
Так что, вообще говоря, да, только HTTP может определять имя хоста назначения в HAProxy... Однако, если TCP-клиент, подключающийся к HAProxy, отправляет адрес назначения (IP или FQDN), можно удалить эту информацию и использовать ее для целей маршрутизации.,
Я представляю своего дилера по покеру в Minecraft:
#starting from top of file, for completeness.
global
user haproxy
group haproxy
#setting tcp mode here is required, won't work if in frontend area!
defaults
mode tcp
#setting up the HAProxy listener:
frontend frontend-name
bind :25565
tcp-request inspect-delay 3s
#ACLs for 1.9 and newer clients:
acl mojang req.payload(5,16) -m sub sub1.domain.tld1
acl bungee req.payload(5,16) -m sub sub2.domain.tld1
acl bungee req.payload(5,16) -m sub sub1.domain.tld2
acl nukkit req.payload(5,16) -m sub sub3.domain.tld1
#ACLs for 1.8 and older clients, keeping pinger working:
acl mojang req.payload(4,16) -m sub sub1.domain.tld1
acl bungee req.payload(4,16) -m sub sub2.domain.tld1
acl bungee req.payload(4,16) -m sub sub1.domain.tld2
acl nukkit req.payload(4,16) -m sub sub3.domain.tld1
#Accept connections if matching an ACL above:
tcp-request content accept if bungee
tcp-request content accept if mojang
tcp-request content accept if nukkit
#Route connection to appropriate backend server:
use_backend minecraft.bungee if bungee
use_backend minecraft.mojang if mojang
use_backend minecraft.nukkit if nukkit
#backend servers - one bungee network, one notchian server, one nukkit server:
backend minecraft.bungee
#here we're directing the connection to bungee on 127.0.0.1:25566
#We're also sending the proxy-protocol(v2) to bungee (check conf!)
server bungee-server 127.0.0.1:25566 send-proxy-v2
backend minecraft.mojang
#Mojang servers can't use the proxy-procotol, so not sending it
server mojang-server 127.0.0.2:25567
backend mincraft.nukkit
#nukkit will never work here, as Bedrock is based on UDP, not TCP!
server sponge-server 127.0.0.3:25568
#EoF
Это базовая настройка и работает. Моя производственная установка значительно отличается, используя параметры, которые требует моя установка.
Теперь все сводится к - вы можете найти хост назначения в пакете, чтобы вы могли искать его с полезной нагрузкой HAProxy?
AFAIK, вы не можете сделать это на основе домена. HTTP может работать так, потому что он имеет специальный Host
заголовок, который браузеры (в данном случае обратные прокси) могут понять и принимать решения на его основе.
На других протоколах TCP я не знаю ничего подобного. Определенно не по SSH.