Вопрос или проблема
Я хочу перенаправить Microsoft Remote Desktop на сервере Linux, предполагая, что удаленный Windows-хост имеет адрес 192.168.1.100
, я хочу запустить:
socat TCP4-LISTEN:3389,fork TCP4:192.168.1.100:3389
socat UDP4-LISTEN:3389,fork UDP4:192.168.1.100:3389
Это работает нормально, когда я запускаю службу вручную в оболочке, но я хочу запустить ее с помощью systemd
и записывать логи в /var/log/socat-rdp.log
.
После нескольких попыток я могу запустить службу следующим образом:
[Unit]
Description=Socat RDP Forwarding Service
After=network.target
[Service]
Type=forking
User=root
ExecStart=/bin/sh -c "/usr/bin/socat TCP4-LISTEN:3389,fork TCP4:192.168.3.153:3389 > /var/log/socat-rdp.log 2>&1 & /usr/bin/socat UDP4-LISTEN:3389,fork UDP4:192.168.3.153:3389 > /var/log/socat-rdp.log 2>&1 &"
ExecStop=/bin/kill $MAINPID
[Install]
WantedBy=multi-user.target
Эта конфигурация запускается и работает обычно, но когда я останавливаю службу с помощью systemctl stop socat-rdp
, она возвращает код ошибки 1, хотя процесс socat
завершен как обычно.
Существуют ли лучшие решения?
Я нашел альтернативное решение для проблемы с запуском нескольких экземпляров socat и перенаправлением как TCP, так и UDP трафика. Вместо того чтобы использовать systemd для управления службой, я использовал Docker для достижения желаемого результата.
Я нашел образ Docker alpine/socat
и использую Docker Compose для запуска двух экземпляров socat
одновременно для TCP и UDP. Вот мой файл Docker Compose:
---
services:
socat_rdp_tcp:
image: alpine/socat
container_name: socat_rdp_tcp
command: "TCP-LISTEN:3389,fork TCP:192.168.1.100:3389"
ports:
- 3389:3389
socat_rdp_udp:
image: alpine/socat
container_name: socat_rdp_udp
command: "UDP-LISTEN:3389,fork UDP:192.168.1.100:3389"
ports:
- 3389:3389/udp
Образ Docker:
alpine/socat
Когда вы запускаете команду socat напрямую в терминале и завершаете их (возможно, killall socat ?), возвращаемый код – Exit 143?
Самый простой грязный хак – использовать SuccessExitStatus=143 в разделе [Service].
Ответ или решение
Для настройки пересылки трафика RDP (Remote Desktop Protocol) на сервере Linux с использованием socat
, вам потребуется управлять как TCP, так и UDP трафиком. Несмотря на то что вы можете запускать эти команды вручную в терминале, использование systemd
для автоматизации этого процесса может быть более эффективным и надежным.
Подход через systemd
В вашем случае вы уже создали службу systemd
, которая правильно настраивает socat
для передачи обоих типов трафика. Однако есть некоторые аспекты, которые можно улучшить для предотвращения ошибок при остановке службы.
Вот модифицированный пример вашего файла службы socat.service
:
[Unit]
Description=Socat RDP Forwarding Service
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/socat TCP4-LISTEN:3389,fork TCP4:192.168.1.100:3389 > /var/log/socat-rdp.log 2>&1 &
ExecStart=/usr/bin/socat UDP4-LISTEN:3389,fork UDP4:192.168.1.100:3389 >> /var/log/socat-rdp.log 2>&1 &
SuccessExitStatus=143
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Объяснение параметров:
-
Type=simple: Указывает
systemd
, что служба не создает дочерний процесс и что основной процесс – это те команды, которые запускаются вExecStart
. -
SuccessExitStatus=143: Это помогает избежать ошибок остановки, когда
socat
завершает работу с кодом 143 (что может происходить при нормальном завершении работы через сигнал SIGTERM). -
RemainAfterExit=yes: Указывает, что служба должна считаться активной даже после завершения всех дочерних процессов, что может быть полезно в вашем случае.
-
& в ExecStart: Обратите внимание, что использование
&
в команде может привести к тому, что процессы будут работать в фоновом режиме, что не всегда является желаемым поведением вsystemd
.
Альтернативный подход через Docker
Как вы упомянули в дальнейшем, использование Docker для развертывания socat
является интересным подходом с возможностью изоляции среды выполнения. Вот ваш файл docker-compose.yml
, который вы уже предложили:
version: '3'
services:
socat_rdp_tcp:
image: alpine/socat
container_name: socat_rdp_tcp
command: "TCP-LISTEN:3389,fork TCP:192.168.1.100:3389"
ports:
- 3389:3389
socat_rdp_udp:
image: alpine/socat
container_name: socat_rdp_udp
command: "UDP-LISTEN:3389,fork UDP:192.168.1.100:3389"
ports:
- 3389:3389/udp
С помощью этого подхода вы можете легко управлять экземплярами socat
как контейнерами, что дает больше гибкости при обновлениях и масштабировании.
Заключение
Оба подхода – использование systemd
или Docker – имеют свои плюсы и минусы. Если вы предпочитаете оставаться на базе Linux и использовать нативное управление процессами, улучшение конфигурации systemd
– это отличный выбор. В противном случае, если вы открыты к контейнеризации, Docker может значительно упростить управление сервисом и его зависимостями.
Убедитесь, что вы логируете выходные данные socat
для дальнейшего анализа, чтобы иметь возможность быстро выявлять и устранять возможные проблемы.
Теперь вы обладаете всеми необходимыми указаниями для настройки вашего сервиса перехвата трафика RDP с помощью socat
, как через systemd
, так и с использованием Docker.