HAproxy: различия между версиями
Mirsem (обсуждение | вклад) |
Mirsem (обсуждение | вклад) |
||
(не показано 12 промежуточных версий этого же участника) | |||
Строка 235: | Строка 235: | ||
<br>Если же у нас ПК в домене, то стоит учесть, стандартный RDP-клиент Windows "брезгует" и при подключении к HAproxy не передаёт ИМЯ пользователя, а первые 9 СИМВОЛОВ. Если же проворачивать такое напрямую, то клиент будет передавать имя пользователя. | <br>Если же у нас ПК в домене, то стоит учесть, стандартный RDP-клиент Windows "брезгует" и при подключении к HAproxy не передаёт ИМЯ пользователя, а первые 9 СИМВОЛОВ. Если же проворачивать такое напрямую, то клиент будет передавать имя пользователя. | ||
<br>Есть два решения данной проблемы: | <br>Есть два решения данной проблемы: | ||
*Использовать '''АЛЬТЕРНАТИВНЫЙ''' клиент RDP под Windows (как пример, mRemoteNG) | *Использовать '''АЛЬТЕРНАТИВНЫЙ''' клиент RDP под Windows (как пример, mRemoteNG или Parallels Client) | ||
*Сделать костыль со стороны ACL (быстрое решение проблемы, но неправильное) | *Сделать костыль со стороны ACL (быстрое решение проблемы, но неправильное) | ||
<br>С первым вариантом вроде бы всё понятно. А второй требует внимания. В ACL мы будем писать не просто имя пользователя, а по вот такой форме: | <br>С первым вариантом вроде бы всё понятно. А второй требует внимания. В ACL мы будем писать не просто имя пользователя, а по вот такой форме: | ||
Строка 247: | Строка 247: | ||
== Процесс добавления новых пользователей в ACL == | |||
'''Данный пункт предназначен для | '''Данный пункт предназначен не для всех.''' | ||
<br> | <br> | ||
Краткая информация: | Краткая информация: | ||
<pre>IP: 10.10.76.103 / 10.10.76.11 | <pre>IP: 10.10.76.103 / 10.10.76.11 | ||
Пользователь: user | Пользователь: user | ||
Пароль: | Пароль: Стандартный. </pre> | ||
Подключаемся к серверу по SSH. | Подключаемся к серверу по SSH. | ||
Строка 268: | Строка 266: | ||
'''''В терминале работает автодополнение по клавише TAB''''' | '''''В терминале работает автодополнение по клавише TAB''''' | ||
# Сохраняем файл и выходим. | # Сохраняем файл и выходим. | ||
< | <code>Ctrl + s</code> <code>Ctrl + x</code> | ||
# Перезапускаем HAproxy. | # Перезапускаем HAproxy. | ||
<pre>sudo systemctl restart haproxy</pre> | <pre>sudo systemctl restart haproxy</pre> | ||
# Если после перезапуска HAproxy вам выдает: <code>Warning: The unit file, source configuration file or drop-ins of haproxy.service changed on disk. Run 'systemctl --user daemon-reload' to reload units.</code> Выполните эту команду: | |||
<pre>sudo systemctl --user daemon-reload</pre> | |||
# Profit! | # Profit! | ||
== Процесс добавления нового RDP сервера в HAproxy == | |||
'''Данный | |||
'''Данный раздел предназначен не для всех.''' | |||
=== Краткая информация === | |||
<pre> | |||
<pre>IP: 10.10.76.103 / 10.10.76.11 | IP: 10.10.76.103 / 10.10.76.11 | ||
Пользователь: user | Пользователь: user | ||
Пароль: | Пароль: Стандартный | ||
</pre> | |||
Подключитесь к серверу по SSH. Конфигурационный файл HAproxy расположен по пути: <code>/etc/haproxy/haproxy.cfg</code> | |||
=== Пошаговая инструкция по добавлению нового сервера в HAproxy (пример: Server2 с IP <code>10.10.10.10</code>) === | |||
Важно! Перед началом работы создайте резервную копию конфигурационного файла: | |||
<pre> | |||
sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.old | |||
</pre> | |||
Откройте файл для редактирования с помощью nano: | |||
<pre> | |||
sudo nano /etc/haproxy/haproxy.cfg | |||
</pre> | |||
В конфигурационном файле найдите блок, начинающийся с <code>frontend ft_rdp</code>. В этом блоке находятся строки, похожие на: | |||
<pre> | |||
acl remoteRDSXX_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDSXX | |||
</pre> | |||
В конце этого блока добавьте новую строку для вашего сервера. В нашем примере, для добавления Server2, новая строка будет выглядеть так: | |||
<pre> | |||
acl remoteServer2_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteServer2 | |||
</pre> | |||
[[Файл:frontendHAproxy.png|600px|thumb|center|Блок frontend ft_rdp]] | |||
[[Файл:ACLHaproxy.png|600px|thumb|center|Пример написания ACL]] | |||
Далее найдите блок команд, написанных по следующему принципу: | |||
<pre> | |||
use_backend remoteRDSXX_BK | |||
<pre> | |||
</pre> | </pre> | ||
В конце этого блока добавьте новую строку. В нашем случае, она будет выглядеть так: | |||
<pre> | |||
use_backend remoteServer2_BK if remoteServer2_ACL | |||
</pre> | |||
[[Файл:backendHaproxy.png|600px|thumb|center|Блок use_backend и пример написания]] | |||
Теперь перейдите в конец файла, перед строкой: | |||
<pre> | |||
backend DF_RDP | |||
</pre> | |||
Перед этой строкой необходимо добавить конфигурацию для нового RDP сервера. В данном примере мы добавляем Server2 с IP <code>10.10.10.10</code>, поэтому итоговый код будет следующим: | |||
<pre> | |||
backend remoteServer2_BK | |||
mode tcp | |||
<code> | balance leastconn | ||
log global | |||
stick-table type string len 32 size 10k expire 8h | |||
stick on req.rdp_cookie(mstshash),bytes(0,19) | |||
option tcplog | |||
tcp-check connect port 3389 | |||
default-server inter 3s rise 2 fall 3 | |||
server TS11 10.10.10.10:3389 weight 10 check | |||
</pre> | |||
Важно! В последней строке, значение <code>TS11</code> необходимо заполнять по следующей форме: <code>TSxx+1</code>, где xx - номер предыдущего сервера в списке. | |||
[[Файл:backendHaproxyc.png|600px|thumb|center|Пример написания backend]] | |||
Сохраните файл и выйдите из редактора nano. | |||
<pre> | |||
Ctrl + O (для сохранения) | |||
Ctrl + X (для выхода) | |||
</pre> | |||
Создайте файл ACL для нового сервера. Пример: | |||
<pre> | |||
sudo touch /etc/haproxy/remoteServer2 | |||
</pre> | |||
Перезапустите службу HAproxy для применения изменений. | |||
<pre> | |||
sudo systemctl restart haproxy | |||
</pre> | |||
Успех! | |||
=== План отката (восстановление предыдущей конфигурации) === | |||
Скопируйте резервную копию конфигурационного файла на место текущего. | |||
<pre> | |||
<pre>sudo cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg</pre> | sudo cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg | ||
</pre> | |||
< | Перезапустите службу HAproxy. | ||
<pre> | |||
sudo systemctl restart haproxy | |||
</pre> | |||
Если после перезапуска HAproxy вам выдает: <code>Warning: The unit file, source configuration file or drop-ins of haproxy.service changed on disk. Run 'systemctl --user daemon-reload' to reload units.</code> Выполните эту команду: | |||
<pre>sudo systemctl --user daemon-reload</pre> | |||
Успех! (Система вернулась к предыдущему состоянию) | |||
== Итог == | == Итог == |
Текущая версия от 08:04, 27 марта 2025
Разворачивание HAproxy и настройка единой точки входа для RDP на основе ACL
Данная статья вкратце рассказывает, как реализовать единую точку входа, используя HAproxy и ACL для RDP-серверов.
Всё делалось на базе Ubuntu Server. На других дистрибутивах Linux могут потребоваться дополнительные шаги по установке.
Данная страница служит напоминанием автору, как это реализовано, для быстрого развёртывания подобного на другом оборудовании и отладки работы уже существующих вариантов.
Установка HAproxy
Для быстрой установки HAproxy перейдите на этот сайт и выберите, какая у вас ОС и какая версия HAproxy вас интересует. Лучше всего выбирать версию 3.0 LTS.

Получите готовый набор команд для установки в терминале.
Первый и самый простой этап выполнен. Переходим к этапу настройки Haproxy.
Конфигурация HAproxy
После установки перейдите в конфиг HAproxy для настройки. Он находится по пути /etc/haproxy/haproxy.cfg
Пример конфига для единой точки входа:
Замените #IPrds* на IP своего RDS
global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 1000 user haproxy group haproxy daemon stats socket /tmp/haproxy.sock ssl-server-verify none defaults mode tcp option tcplog option tcp-smart-accept option tcp-smart-connect frontend ft_rdp mode tcp bind *:3389 name rdp #timeout client 1h persist rdp-cookie log global option tcplog tcp-request inspect-delay 2s tcp-request content accept if RDP_COOKIE acl remoteRDSH01_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDSH01 acl remoteRDSH02_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDSH02 acl remoteRDSH03_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDSH03 acl remoteRDSH04_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDSH04 acl remoteRDS01_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDS01 acl remoteRDS02_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDS02 acl remoteRDS03_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDS03 acl remoteRDS04_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDS04 acl remoteRDS05_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDS05 acl remoteRDS06_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDS06 use_backend remoteRDSH01_BK if remoteRDSH01_ACL use_backend remoteRDSH02_BK if remoteRDSH02_ACL use_backend remoteRDSH03_BK if remoteRDSH03_ACL use_backend remoteRDSH04_BK if remoteRDSH04_ACL use_backend remoteRDS01_BK if remoteRDS01_ACL use_backend remoteRDS02_BK if remoteRDS02_ACL use_backend remoteRDS03_BK if remoteRDS03_ACL use_backend remoteRDS04_BK if remoteRDS04_ACL use_backend remoteRDS05_BK if remoteRDS05_ACL use_backend remoteRDS06_BK if remoteRDS06_ACL default_backend DF_RDP backend remoteRDSH01_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS02 #IPrds1:3389 weight 10 check backend remoteRDSH02_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS03 #IPrds2:3389 weight 10 check backend remoteRDSH03_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS04 #IPrds3:3389 weight 10 check backend remoteRDSH04_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS05 #IPrds4:3389 weight 10 check backend remoteRDS01_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS06 #IPrds5:3389 weight 10 check backend remoteRDS02_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS07 #IPrds6:3389 weight 10 check backend remoteRDS03_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS08 #IPrds7:3389 weight 10 check backend remoteRDS04_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS09 #IPrds8:3389 weight 10 check backend remoteRDS05_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS10 #IPrds9:3389 weight 10 check backend remoteRDS06_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS11 #IPrds10:3389 weight 10 check backend DF_RDP mode tcp balance leastconn log global option tcplog stick-table type string len 32 size 10k expire 8h stick on rdp_cookie(mstshash),bytes(0,6) option tcp-check tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS01 #IPrds11:3389 weight 10 check listen stats bind *:9000 mode http stats enable #stats hide-version stats show-node stats realm Haproxy\ Statistics stats uri /
Теперь давайте объясню главные моменты, что написано в этом файле.
acl remoteRDSH##_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDSHxx
Данная команда обозначает, что для RDS## требуется RDP-куки, и она смотрит первые 20 байтов и сравнивает их с файлом ACL.
use_backend remoteRDSHxx_BK if remoteRDSHxx_ACL
Обозначает, что если RDP-куки нашлась в ACL, то перенаправить на нужный RDS.
Так же в конфиге есть DF_RDP
. Он нужен, чтобы отправлять всех пользователей, которых нет ни в одном ACL, туда. Так же, если его не будет, то мы не сможем подключиться. Поэтому можете написать IP, которого нет. Костыль? Да :)
И самое последнее. Если вы откроете браузер и перейдёте на IP:9000 машины, где крутится HAproxy, вы получите статистику.

Создание ACL для HAproxy
Стоит учесть, что файлы ACL /etc/haproxy/remoteRDSHxx
ДОЛЖНЫ быть созданы ЗАРАНЕЕ. Иначе HAproxy откажется запускаться. Файлы могут быть полностью пустыми. Так что для простоты просто используйте команду:
touch remoteRDSHxx
В RDP-куки НЕ передаётся имя пользователя ЕСЛИ ОНО НА РУССКОМ. Создавайте пользователей ТОЛЬКО на английском.
Редактировать ACL "на горячую" нельзя. Изменения вступят в силу лишь ПОСЛЕ перезапуска HAproxy.
sudo systemctl restart haproxy
Заполнение ACL и как это делать правильно. Стоит сразу определить, что используют пользователи:
- Windows со стандартным RDP-клиентом / "Толстый" клиент
- Linux и его зоопарк RDP-клиентов / "Тонкий" клиент
Windows
Если у нас ПК не в домене и подключение происходит просто по имени пользователя, то проблем у нас нет. Можем спокойно открывать файлы с ACL и пишем всех пользователей с новой строчки. Как тут:
admin 1060Admin 960Admin
Если же у нас ПК в домене, то стоит учесть, стандартный RDP-клиент Windows "брезгует" и при подключении к HAproxy не передаёт ИМЯ пользователя, а первые 9 СИМВОЛОВ. Если же проворачивать такое напрямую, то клиент будет передавать имя пользователя.
Есть два решения данной проблемы:
- Использовать АЛЬТЕРНАТИВНЫЙ клиент RDP под Windows (как пример, mRemoteNG или Parallels Client)
- Сделать костыль со стороны ACL (быстрое решение проблемы, но неправильное)
С первым вариантом вроде бы всё понятно. А второй требует внимания. В ACL мы будем писать не просто имя пользователя, а по вот такой форме:
Имя_Пользователя@Домен
Но мы должны оставить ТОЛЬКО 9 символов. Это лишь быстрое решение проблемы, стоит рассмотреть вариант смены RDP-клиента.
Linux
Если же у нас Linux-машина и/или "тонкий" клиент, то мы можем спокойно писать имя пользователя, не важно, в домене ли ПК или нет. Клиенты под Linux передают столько символов, сколько напишут, и ТОЛЬКО имя пользователя, даже если пользователь писал домен.

Процесс добавления новых пользователей в ACL
Данный пункт предназначен не для всех.
Краткая информация:
IP: 10.10.76.103 / 10.10.76.11 Пользователь: user Пароль: Стандартный.
Подключаемся к серверу по SSH.
Все ACL лежат по пути /etc/haproxy/
.
Все имена РДС совпадают с именами в AD.
План действий по добавлению пользователя:
- Узнаем, на каком из РДС будет работать пользователь.
- Получаем имя учетной записи пользователя из AD.
- Открываем через nano ACL нужного РДС и заносим нового пользователя с новой строки в самом конце файла.
sudo nano /etc/haproxy/remoteRDSXX
В терминале работает автодополнение по клавише TAB
- Сохраняем файл и выходим.
Ctrl + s
Ctrl + x
- Перезапускаем HAproxy.
sudo systemctl restart haproxy
- Если после перезапуска HAproxy вам выдает:
Warning: The unit file, source configuration file or drop-ins of haproxy.service changed on disk. Run 'systemctl --user daemon-reload' to reload units.
Выполните эту команду:
sudo systemctl --user daemon-reload
- Profit!
Процесс добавления нового RDP сервера в HAproxy
Данный раздел предназначен не для всех.
Краткая информация
IP: 10.10.76.103 / 10.10.76.11 Пользователь: user Пароль: Стандартный
Подключитесь к серверу по SSH. Конфигурационный файл HAproxy расположен по пути: /etc/haproxy/haproxy.cfg
Пошаговая инструкция по добавлению нового сервера в HAproxy (пример: Server2 с IP 10.10.10.10
)
Важно! Перед началом работы создайте резервную копию конфигурационного файла:
sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.old
Откройте файл для редактирования с помощью nano:
sudo nano /etc/haproxy/haproxy.cfg
В конфигурационном файле найдите блок, начинающийся с frontend ft_rdp
. В этом блоке находятся строки, похожие на:
acl remoteRDSXX_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteRDSXX
В конце этого блока добавьте новую строку для вашего сервера. В нашем примере, для добавления Server2, новая строка будет выглядеть так:
acl remoteServer2_ACL req.rdp_cookie(mstshash),bytes(0,19) -m str -i -f /etc/haproxy/remoteServer2


Далее найдите блок команд, написанных по следующему принципу:
use_backend remoteRDSXX_BK
В конце этого блока добавьте новую строку. В нашем случае, она будет выглядеть так:
use_backend remoteServer2_BK if remoteServer2_ACL

Теперь перейдите в конец файла, перед строкой:
backend DF_RDP
Перед этой строкой необходимо добавить конфигурацию для нового RDP сервера. В данном примере мы добавляем Server2 с IP 10.10.10.10
, поэтому итоговый код будет следующим:
backend remoteServer2_BK mode tcp balance leastconn log global stick-table type string len 32 size 10k expire 8h stick on req.rdp_cookie(mstshash),bytes(0,19) option tcplog tcp-check connect port 3389 default-server inter 3s rise 2 fall 3 server TS11 10.10.10.10:3389 weight 10 check
Важно! В последней строке, значение TS11
необходимо заполнять по следующей форме: TSxx+1
, где xx - номер предыдущего сервера в списке.

Сохраните файл и выйдите из редактора nano.
Ctrl + O (для сохранения) Ctrl + X (для выхода)
Создайте файл ACL для нового сервера. Пример:
sudo touch /etc/haproxy/remoteServer2
Перезапустите службу HAproxy для применения изменений.
sudo systemctl restart haproxy
Успех!
План отката (восстановление предыдущей конфигурации)
Скопируйте резервную копию конфигурационного файла на место текущего.
sudo cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg
Перезапустите службу HAproxy.
sudo systemctl restart haproxy
Если после перезапуска HAproxy вам выдает: Warning: The unit file, source configuration file or drop-ins of haproxy.service changed on disk. Run 'systemctl --user daemon-reload' to reload units.
Выполните эту команду:
sudo systemctl --user daemon-reload
Успех! (Система вернулась к предыдущему состоянию)
Итог
Если теперь подключиться через RDP-клиент к серверу, где мы развернули HAProxy, нас должно перенаправить на один из RDS на основе ACL. HAProxy почти не потребляет ресурсов. Виртуалки с 2 ГБ ОЗУ и одним процессором должно хватить.
- Плюсы данного решения:
- Единая точка входа на множество серверов.
- Слабое потребление ресурсов.

- Минусы данного решения:
- Слабая отказоустойчивость. Если один из серверов не работает, то HAProxy будет до последнего перенаправлять на этот сервер.
- Стандартный RDP-клиент в Windows некорректно работает с таким решением.