Защита RDP от перебора паролей через MikroTik
Remote Desktop Protocol (RDP) — один из самых атакуемых сервисов в интернете. Порт 3389 постоянно сканируется ботнетами, а количество попыток brute-force может достигать тысяч в час. Успешный взлом RDP приводит к шифрованию данных ransomware, краже информации или использованию сервера в качестве звена ботнета.
MikroTik RouterOS предоставляет несколько уровней защиты RDP: от простого ограничения по IP до полного сокрытия сервиса за VPN. В данной статье мы рассмотрим пять методов защиты, от базовых до продвинутых, и покажем как комбинировать их для максимальной безопасности.
Описание
Масштаб проблемы
Статистика показывает, что открытый порт 3389 в интернете начинает получать атаки в течение минут после появления. Типичная картина:
- 500–5000 попыток подбора пароля в сутки с одного IP
- Ботнеты используют тысячи IP-адресов для распределённого перебора
- Словари содержат миллионы комбинаций логин/пароль
- Средний успешный взлом простого пароля — от нескольких часов до нескольких дней
Даже «сложный» пароль не является достаточной защитой, потому что:
- Уязвимости в самом RDP-протоколе (BlueKeep, DejaBlue) позволяют атаку без пароля
- Утёкшие учётные данные из других сервисов часто подходят
- Credential stuffing автоматизирован и работает 24/7
Что мы будем защищать
Типичная топология: MikroTik-роутер стоит перед сервером с RDP. Внешний IP — на WAN-интерфейсе роутера, RDP-сервер в LAN.
codeИнтернет → [ether1: WAN] MikroTik [bridge1: LAN] → RDP-сервер (192.168.88.100:3389)
Без защиты администратор обычно настраивает простой dst-nat:
[admin@MikroTik] ># НЕБЕЗОПАСНО! Прямой проброс RDP без защиты /ip/firewall/nat add chain=dstnat in-interface=ether1 protocol=tcp dst-port=3389 \ action=dst-nat to-addresses=192.168.88.100 to-ports=3389
Эта конфигурация открывает RDP всему интернету. Рассмотрим, как это исправить.
Настройка
Метод 1: Port Knocking для RDP
Port Knocking — техника, при которой доступ к порту открывается только после обращения к определённой последовательности «секретных» портов. Это как кодовый замок: нужно «постучать» в правильном порядке.
Принцип работы:
- Пользователь отправляет пакет на порт 8291 → IP добавляется в
rdp-stage1 - Затем на порт 6543 → IP перемещается в
rdp-stage2 - Затем на порт 4871 → IP перемещается в
rdp-allowed - Только IP из
rdp-allowedполучает доступ к RDP
[admin@MikroTik] >/ip/firewall/filter # Stage 1: Стучим в первый порт (8291) add chain=input in-interface=ether1 protocol=tcp dst-port=8291 \ action=add-src-to-address-list \ address-list=rdp-stage1 address-list-timeout=15s \ comment="Port Knock Stage 1" # Stage 2: Стучим во второй порт (6543), но только если прошли Stage 1 add chain=input in-interface=ether1 protocol=tcp dst-port=6543 \ src-address-list=rdp-stage1 \ action=add-src-to-address-list \ address-list=rdp-stage2 address-list-timeout=15s \ comment="Port Knock Stage 2" # Stage 3: Стучим в третий порт (4871), но только если прошли Stage 2 add chain=input in-interface=ether1 protocol=tcp dst-port=4871 \ src-address-list=rdp-stage2 \ action=add-src-to-address-list \ address-list=rdp-allowed address-list-timeout=1h \ comment="Port Knock Stage 3 - Access Granted" # Разрешаем RDP только для прошедших Port Knock add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ src-address-list=rdp-allowed \ action=accept comment="Allow RDP after Port Knock" # Блокируем RDP для всех остальных add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ action=drop comment="Block RDP without Port Knock"
Для «стука» на клиентской стороне можно использовать утилиту knock (Linux) или простые PowerShell-команды:
[admin@MikroTik] ># PowerShell на клиенте (Windows) Test-NetConnection -ComputerName <router-ip> -Port 8291 Start-Sleep 1 Test-NetConnection -ComputerName <router-ip> -Port 6543 Start-Sleep 1 Test-NetConnection -ComputerName <router-ip> -Port 4871 Start-Sleep 2 # Теперь можно подключаться по RDP mstsc /v:<router-ip>
Плюсы: порт 3389 невидим для сканеров, нет нагрузки на роутер. Минусы: неудобно для пользователей, не защищает от перехвата последовательности.
Метод 2: Rate Limiting через каскад address-list
Этот метод автоматически блокирует IP-адреса, которые слишком часто подключаются к RDP. Используется каскад из нескольких стадий:
[admin@MikroTik] >/ip/firewall/filter # Шаг 1: Если IP уже в чёрном списке — блокируем add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ src-address-list=rdp-blocked action=drop \ log=yes log-prefix="RDP-BLOCKED" \ comment="Drop blocked RDP attackers" # Шаг 2: Третья попытка за 1 минуту — блокировка add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ src-address-list=rdp-stage2 action=add-src-to-address-list \ address-list=rdp-blocked address-list-timeout=24h \ comment="RDP brute-force -> block for 24h" # Шаг 3: Вторая попытка за 1 минуту — stage2 add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ src-address-list=rdp-stage1 action=add-src-to-address-list \ address-list=rdp-stage2 address-list-timeout=1m \ comment="RDP stage2" # Шаг 4: Первая попытка — stage1 add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ connection-state=new action=add-src-to-address-list \ address-list=rdp-stage1 address-list-timeout=1m \ comment="RDP stage1" # Шаг 5: Разрешаем RDP (для не заблокированных) add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ connection-state=new action=accept \ comment="Allow RDP (rate limited)"
Логика работы:
- Первое подключение → IP в
rdp-stage1(таймер 1 минута) - Второе подключение за минуту → IP в
rdp-stage2(таймер 1 минута) - Третье подключение за минуту → IP в
rdp-blockedна 24 часа - Легитимный пользователь вводит пароль с 1-2 попыток и проходит
- Бот, перебирающий пароли, блокируется после 3-й попытки
Плюсы: автоматическая работа, не требует действий от пользователя. Минусы: RDP всё ещё виден сканерам, 2 попытки остаются до блокировки.
Метод 3: Whitelist — доступ только с определённых IP
Самый простой и надёжный метод, если у пользователей RDP есть статические IP-адреса:
[admin@MikroTik] ># Создаём whitelist разрешённых IP /ip/firewall/address-list add address=203.0.113.10 list=rdp-whitelist comment="Office main" add address=198.51.100.0/24 list=rdp-whitelist comment="Office subnet" add address=192.0.2.50 list=rdp-whitelist comment="Admin home IP" # Firewall правила /ip/firewall/filter # Разрешаем RDP только из whitelist add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ src-address-list=rdp-whitelist action=accept \ comment="Allow RDP from whitelist only" # Блокируем все остальные попытки RDP add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ action=drop log=yes log-prefix="RDP-DENIED" \ comment="Drop all other RDP"
Для динамического обновления whitelist можно использовать скрипт. Например, сотрудник отправляет специальный запрос, и его IP добавляется на время:
[admin@MikroTik] ># Добавление временного доступа через скрипт (вызывается вручную) /system/script add name=rdp-temp-access source={ :local ip $tempIP :local hours $tempHours :if ([:len $ip] > 0) do={ /ip/firewall/address-list add address=$ip list=rdp-whitelist \ timeout="$($hours)h" comment="Temp RDP access" :log info "RDP temp access granted to $ip for $hours hours" } }
Плюсы: максимальная безопасность, нулевая поверхность атаки. Минусы: не работает с динамическими IP, требует ручного управления списком.
Метод 4: VPN → RDP (рекомендуемый)
Лучший подход — полностью закрыть RDP из интернета и предоставлять доступ только через VPN. WireGuard — оптимальный выбор благодаря простоте и производительности.
Шаг 1: Настройка WireGuard на MikroTik
[admin@MikroTik] ># Создаём WireGuard-интерфейс /interface/wireguard add name=wg-rdp listen-port=51820 mtu=1420 \ comment="WireGuard for RDP access" # Получаем публичный ключ сервера /interface/wireguard/print where name=wg-rdp # Добавляем peer (клиент) /interface/wireguard/peers add interface=wg-rdp \ public-key="<CLIENT_PUBLIC_KEY>" \ allowed-address=10.10.10.2/32 \ comment="Admin laptop" # IP для WireGuard-интерфейса /ip/address add address=10.10.10.1/24 interface=wg-rdp comment="WireGuard RDP network"
Шаг 2: Firewall — разрешаем WireGuard, запрещаем прямой RDP
[admin@MikroTik] >/ip/firewall/filter # Разрешаем WireGuard из интернета add chain=input in-interface=ether1 protocol=udp dst-port=51820 \ action=accept comment="Allow WireGuard" # Разрешаем RDP только из WireGuard-сети add chain=forward src-address=10.10.10.0/24 \ dst-address=192.168.88.100 protocol=tcp dst-port=3389 \ action=accept comment="Allow RDP from WireGuard only" # Блокируем прямой RDP из интернета add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ action=drop log=yes log-prefix="RDP-DIRECT-DROP" \ comment="Block direct RDP from internet"
Шаг 3: Убираем dst-nat для RDP (если был)
[admin@MikroTik] ># Удаляем прямой проброс RDP /ip/firewall/nat/remove [find where dst-port=3389 action=dst-nat]
Теперь RDP-сервер полностью невидим из интернета. Для подключения пользователь:
- Подключает WireGuard VPN
- Получает IP 10.10.10.2
- Подключается по RDP к 192.168.88.100:3389 через VPN-туннель
Плюсы: порт 3389 закрыт, WireGuard добавляет шифрование, аутентификация по ключам. Минусы: требует установки WireGuard-клиента, минимальная дополнительная настройка.
Метод 5: Нестандартный порт (dst-nat)
Смена порта — не полноценная защита, но затрудняет автоматическое сканирование:
[admin@MikroTik] >/ip/firewall/nat add chain=dstnat in-interface=ether1 protocol=tcp dst-port=47832 \ action=dst-nat to-addresses=192.168.88.100 to-ports=3389 \ comment="RDP on non-standard port"
Пользователь подключается к <router-ip>:47832, а MikroTik перенаправляет на 192.168.88.100:3389.
Важно: смена порта — это «security by obscurity». Продвинутые сканеры (nmap service detection) определят RDP на любом порту. Используйте этот метод только в комбинации с другими.
[admin@MikroTik] ># Обновляем firewall для нестандартного порта /ip/firewall/filter add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ src-address-list=rdp-blocked action=drop \ comment="Drop blocked on non-standard RDP port" # Rate limiting на нестандартном порту add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ connection-state=new src-address-list=rdp-stage2 \ action=add-src-to-address-list \ address-list=rdp-blocked address-list-timeout=24h \ comment="Block after 3 attempts on alt RDP port"
Комбинированный подход (рекомендация)
Лучшая защита — комбинация нескольких методов. Рекомендуемая конфигурация:
Уровень 1: VPN (основной доступ)
- RDP доступен только через WireGuard VPN
- Порт 3389 полностью закрыт из интернета
Уровень 2: Whitelist (резервный доступ)
- Для офисов со статическим IP — прямой доступ через whitelist
- Нестандартный порт + rate limiting
Уровень 3: Мониторинг и блокировка
- Логирование всех попыток доступа
- Автоматическая блокировка brute-force
Полная конфигурация:
[admin@MikroTik] ># === Address Lists === /ip/firewall/address-list add address=203.0.113.10 list=rdp-whitelist comment="Office static IP" # === NAT (нестандартный порт для whitelist) === /ip/firewall/nat add chain=dstnat in-interface=ether1 protocol=tcp dst-port=47832 \ src-address-list=rdp-whitelist \ action=dst-nat to-addresses=192.168.88.100 to-ports=3389 \ comment="RDP NAT for whitelist only" # === Filter === /ip/firewall/filter # Разрешаем WireGuard add chain=input in-interface=ether1 protocol=udp dst-port=51820 \ action=accept comment="Allow WireGuard" # RDP через VPN — разрешаем add chain=forward src-address=10.10.10.0/24 \ dst-address=192.168.88.100 protocol=tcp dst-port=3389 \ action=accept comment="RDP via WireGuard VPN" # RDP blocked list — drop add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ src-address-list=rdp-blocked action=drop \ log=yes log-prefix="RDP-BLOCKED" \ comment="Drop blocked RDP IPs" # RDP rate limiting stages add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ connection-state=new src-address-list=rdp-stage2 \ action=add-src-to-address-list \ address-list=rdp-blocked address-list-timeout=24h \ comment="RDP brute-force block" add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ connection-state=new src-address-list=rdp-stage1 \ action=add-src-to-address-list \ address-list=rdp-stage2 address-list-timeout=1m \ comment="RDP stage2" add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ connection-state=new action=add-src-to-address-list \ address-list=rdp-stage1 address-list-timeout=1m \ comment="RDP stage1" # RDP whitelist — accept (после rate limiting!) add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ src-address-list=rdp-whitelist action=accept \ comment="Allow RDP from whitelist" # Блокируем прямой RDP (порт 3389) из интернета add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ action=drop log=yes log-prefix="RDP-DIRECT-DROP" \ comment="Block direct RDP port 3389" # Блокируем нестандартный порт для не-whitelist add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \ action=drop log=yes log-prefix="RDP-DENIED" \ comment="Block RDP alt port for non-whitelist"
Проверка
Мониторинг address-list
[admin@MikroTik] ># Список заблокированных IP /ip/firewall/address-list/print where list=rdp-blocked # Количество заблокированных /ip/firewall/address-list/print count-only where list=rdp-blocked # Whitelist /ip/firewall/address-list/print where list=rdp-whitelist
Просмотр логов
[admin@MikroTik] ># Все RDP-связанные записи в логе /log/print where message~"RDP" # Только заблокированные /log/print where message~"RDP-BLOCKED" # Попытки прямого подключения к 3389 /log/print where message~"RDP-DIRECT"
Статистика правил firewall
[admin@MikroTik] >/ip/firewall/filter/print stats where comment~"RDP"
Обращайте внимание на счётчики:
- Правило
rdp-blockedс высоким счётчиком → активный brute-force - Правило
RDP-DIRECT-DROPс ненулевым счётчиком → кто-то сканирует порт 3389 - Правило
Allow RDP from whitelist→ легитимные подключения
Проверка доступности RDP
С внешнего хоста проверьте, что порт 3389 закрыт:
[admin@MikroTik] ># С самого MikroTik (проверяем из-под другого IP через bandwidth-test или fetch) /tool/fetch url="https://portchecker.co/check" mode=https
Или используйте внешний сервис проверки портов (например, portchecker.co, canyouseeme.org).
Тест rate limiting
Для проверки работы rate limiting подключитесь к нестандартному порту несколько раз подряд:
[admin@MikroTik] ># Проверяем что IP попал в rdp-stage1 после первого подключения /ip/firewall/address-list/print where list=rdp-stage1 # После третьего — должен быть в rdp-blocked /ip/firewall/address-list/print where list=rdp-blocked
Дополнительные меры
Настройка логирования
Для детального анализа атак настройте отдельную тему логирования:
[admin@MikroTik] >/system/logging add topics=firewall action=remote prefix="FW" \ comment="Firewall logs to remote syslog"
Уведомления в Telegram
Скрипт для отправки уведомлений при блокировке RDP-атакующего:
[admin@MikroTik] >/system/script add name=rdp-alert source={ :local botToken "YOUR_BOT_TOKEN" :local chatId "YOUR_CHAT_ID" :local blockedCount [/ip/firewall/address-list/print count-only where list=rdp-blocked] :if ($blockedCount > 0) do={ :local msg "RDP Alert: $blockedCount IPs blocked in last 24h" /tool/fetch url="https://api.telegram.org/bot$botToken/sendMessage\?chat_id=$chatId&text=$msg" \ mode=https keep-result=no } } /system/scheduler add name=rdp-alert-check interval=1h on-event="/system/script/run rdp-alert"
Network Level Authentication (NLA)
Помимо защиты на MikroTik, обязательно включите NLA на самом RDP-сервере. NLA требует аутентификации до установления RDP-сессии, что значительно снижает нагрузку при brute-force.
На Windows Server:
[admin@MikroTik] ># PowerShell на RDP-сервере Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name 'UserAuthentication' -Value 1
Типичные ошибки
Ошибка 1: Порядок правил firewall
[admin@MikroTik] ># НЕПРАВИЛЬНО! Accept стоит перед rate limiting /ip/firewall/filter add chain=forward protocol=tcp dst-port=3389 action=accept # пропускает ВСЁ add chain=forward protocol=tcp dst-port=3389 src-address-list=rdp-blocked action=drop
В такой конфигурации правило accept сработает первым, и rate limiting никогда не будет задействован.
Решение: всегда ставьте drop-правила перед accept:
[admin@MikroTik] >/ip/firewall/filter add chain=forward protocol=tcp dst-port=3389 src-address-list=rdp-blocked action=drop # ... rate limiting rules ... add chain=forward protocol=tcp dst-port=3389 action=accept
Ошибка 2: Rate limiting на dst-nat порту вместо реального
Если вы используете dst-nat с порта 47832 на 3389, то в цепочке forward пакет уже имеет dst-port=3389 (после NAT). Правила rate limiting нужно создавать для порта, который виден в forward:
[admin@MikroTik] ># При dst-nat 47832→3389: # В chain=forward пакет приходит с dst-port=3389, НЕ 47832! # ПРАВИЛЬНО: rate limit по dst-port=3389 в forward add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ connection-state=new src-address-list=rdp-stage2 \ action=add-src-to-address-list address-list=rdp-blocked \ address-list-timeout=24h # Или используйте connection-nat-dst-port для фильтрации по оригинальному порту
Альтернативный подход: используйте raw prerouting, где порт ещё не транслирован:
[admin@MikroTik] >/ip/firewall/raw add chain=prerouting in-interface=ether1 protocol=tcp dst-port=47832 \ src-address-list=rdp-blocked action=drop
Ошибка 3: Забыл заблокировать стандартный порт 3389
После настройки нестандартного порта многие забывают заблокировать оригинальный 3389:
[admin@MikroTik] ># НЕ ЗАБУДЬТЕ! Даже если dst-nat только на 47832, сканеры найдут 3389 /ip/firewall/filter add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \ action=drop comment="Block standard RDP port"
Ошибка 4: Слишком короткий таймаут блокировки
[admin@MikroTik] ># СЛАБО: 10 минут блокировки — бот просто подождёт address-list-timeout=10m
10 минут блокировки бесполезны против ботнета. Бот переключится на другой IP, а через 10 минут вернётся. Рекомендуемый минимум — 24 часа.
Для особо агрессивных атакующих можно увеличить до 7 дней:
routerosaddress-list-timeout=7d
Ошибка 5: Не настроено логирование
Без логирования вы не узнаете о попытках атаки, пока не станет слишком поздно:
[admin@MikroTik] ># Добавьте log ко всем drop-правилам action=drop log=yes log-prefix="RDP-ATTEMPT"
Без log=yes правило молча отбрасывает пакеты, и вы теряете ценную информацию для анализа угроз.
Ошибка 6: VPN без kill-switch
Если вы используете метод VPN → RDP, но VPN-клиент отключается, некоторые пользователи пытаются подключиться напрямую. Убедитесь, что прямое подключение невозможно даже при сбое VPN:
[admin@MikroTik] ># Убедитесь что dst-nat для RDP через WAN НЕ существует /ip/firewall/nat/print where dst-port=3389 chain=dstnat # Должно быть пусто!
Если dst-nat отсутствует, RDP-сервер физически недоступен из интернета, даже если VPN упал.
Заключение
Защита RDP — это не один метод, а эшелонированная оборона:
- VPN (WireGuard) — основной и самый надёжный метод доступа
- Whitelist — для офисов со статическим IP
- Rate Limiting — автоматическая блокировка brute-force
- Нестандартный порт — дополнительное затруднение для сканеров
- Port Knocking — для продвинутых сценариев
Минимальная рекомендуемая конфигурация: VPN + блокировка порта 3389 из интернета + логирование. Это закрывает 99% атак при минимальной сложности настройки.
Интернет → [ether1: WAN] MikroTik [bridge1: LAN] → RDP-сервер (192.168.88.100:3389)
# НЕБЕЗОПАСНО! Прямой проброс RDP без защиты
/ip/firewall/nat
add chain=dstnat in-interface=ether1 protocol=tcp dst-port=3389 \
action=dst-nat to-addresses=192.168.88.100 to-ports=3389
/ip/firewall/filter
# Stage 1: Стучим в первый порт (8291)
add chain=input in-interface=ether1 protocol=tcp dst-port=8291 \
action=add-src-to-address-list \
address-list=rdp-stage1 address-list-timeout=15s \
comment="Port Knock Stage 1"
# Stage 2: Стучим во второй порт (6543), но только если прошли Stage 1
add chain=input in-interface=ether1 protocol=tcp dst-port=6543 \
src-address-list=rdp-stage1 \
action=add-src-to-address-list \
address-list=rdp-stage2 address-list-timeout=15s \
comment="Port Knock Stage 2"
# Stage 3: Стучим в третий порт (4871), но только если прошли Stage 2
add chain=input in-interface=ether1 protocol=tcp dst-port=4871 \
src-address-list=rdp-stage2 \
action=add-src-to-address-list \
address-list=rdp-allowed address-list-timeout=1h \
comment="Port Knock Stage 3 - Access Granted"
# Разрешаем RDP только для прошедших Port Knock
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
src-address-list=rdp-allowed \
action=accept comment="Allow RDP after Port Knock"
# Блокируем RDP для всех остальных
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
action=drop comment="Block RDP without Port Knock"
# PowerShell на клиенте (Windows)
Test-NetConnection -ComputerName <router-ip> -Port 8291
Start-Sleep 1
Test-NetConnection -ComputerName <router-ip> -Port 6543
Start-Sleep 1
Test-NetConnection -ComputerName <router-ip> -Port 4871
Start-Sleep 2
# Теперь можно подключаться по RDP
mstsc /v:<router-ip>
/ip/firewall/filter
# Шаг 1: Если IP уже в чёрном списке — блокируем
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
src-address-list=rdp-blocked action=drop \
log=yes log-prefix="RDP-BLOCKED" \
comment="Drop blocked RDP attackers"
# Шаг 2: Третья попытка за 1 минуту — блокировка
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
src-address-list=rdp-stage2 action=add-src-to-address-list \
address-list=rdp-blocked address-list-timeout=24h \
comment="RDP brute-force -> block for 24h"
# Шаг 3: Вторая попытка за 1 минуту — stage2
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
src-address-list=rdp-stage1 action=add-src-to-address-list \
address-list=rdp-stage2 address-list-timeout=1m \
comment="RDP stage2"
# Шаг 4: Первая попытка — stage1
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
connection-state=new action=add-src-to-address-list \
address-list=rdp-stage1 address-list-timeout=1m \
comment="RDP stage1"
# Шаг 5: Разрешаем RDP (для не заблокированных)
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
connection-state=new action=accept \
comment="Allow RDP (rate limited)"
# Создаём whitelist разрешённых IP
/ip/firewall/address-list
add address=203.0.113.10 list=rdp-whitelist comment="Office main"
add address=198.51.100.0/24 list=rdp-whitelist comment="Office subnet"
add address=192.0.2.50 list=rdp-whitelist comment="Admin home IP"
# Firewall правила
/ip/firewall/filter
# Разрешаем RDP только из whitelist
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
src-address-list=rdp-whitelist action=accept \
comment="Allow RDP from whitelist only"
# Блокируем все остальные попытки RDP
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
action=drop log=yes log-prefix="RDP-DENIED" \
comment="Drop all other RDP"
# Добавление временного доступа через скрипт (вызывается вручную)
/system/script
add name=rdp-temp-access source={
:local ip $tempIP
:local hours $tempHours
:if ([:len $ip] > 0) do={
/ip/firewall/address-list add address=$ip list=rdp-whitelist \
timeout="$($hours)h" comment="Temp RDP access"
:log info "RDP temp access granted to $ip for $hours hours"
}
}
# Создаём WireGuard-интерфейс
/interface/wireguard
add name=wg-rdp listen-port=51820 mtu=1420 \
comment="WireGuard for RDP access"
# Получаем публичный ключ сервера
/interface/wireguard/print where name=wg-rdp
# Добавляем peer (клиент)
/interface/wireguard/peers
add interface=wg-rdp \
public-key="<CLIENT_PUBLIC_KEY>" \
allowed-address=10.10.10.2/32 \
comment="Admin laptop"
# IP для WireGuard-интерфейса
/ip/address
add address=10.10.10.1/24 interface=wg-rdp comment="WireGuard RDP network"
/ip/firewall/filter
# Разрешаем WireGuard из интернета
add chain=input in-interface=ether1 protocol=udp dst-port=51820 \
action=accept comment="Allow WireGuard"
# Разрешаем RDP только из WireGuard-сети
add chain=forward src-address=10.10.10.0/24 \
dst-address=192.168.88.100 protocol=tcp dst-port=3389 \
action=accept comment="Allow RDP from WireGuard only"
# Блокируем прямой RDP из интернета
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
action=drop log=yes log-prefix="RDP-DIRECT-DROP" \
comment="Block direct RDP from internet"
# Удаляем прямой проброс RDP
/ip/firewall/nat/remove [find where dst-port=3389 action=dst-nat]
/ip/firewall/nat
add chain=dstnat in-interface=ether1 protocol=tcp dst-port=47832 \
action=dst-nat to-addresses=192.168.88.100 to-ports=3389 \
comment="RDP on non-standard port"
# Обновляем firewall для нестандартного порта
/ip/firewall/filter
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
src-address-list=rdp-blocked action=drop \
comment="Drop blocked on non-standard RDP port"
# Rate limiting на нестандартном порту
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
connection-state=new src-address-list=rdp-stage2 \
action=add-src-to-address-list \
address-list=rdp-blocked address-list-timeout=24h \
comment="Block after 3 attempts on alt RDP port"
# === Address Lists ===
/ip/firewall/address-list
add address=203.0.113.10 list=rdp-whitelist comment="Office static IP"
# === NAT (нестандартный порт для whitelist) ===
/ip/firewall/nat
add chain=dstnat in-interface=ether1 protocol=tcp dst-port=47832 \
src-address-list=rdp-whitelist \
action=dst-nat to-addresses=192.168.88.100 to-ports=3389 \
comment="RDP NAT for whitelist only"
# === Filter ===
/ip/firewall/filter
# Разрешаем WireGuard
add chain=input in-interface=ether1 protocol=udp dst-port=51820 \
action=accept comment="Allow WireGuard"
# RDP через VPN — разрешаем
add chain=forward src-address=10.10.10.0/24 \
dst-address=192.168.88.100 protocol=tcp dst-port=3389 \
action=accept comment="RDP via WireGuard VPN"
# RDP blocked list — drop
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
src-address-list=rdp-blocked action=drop \
log=yes log-prefix="RDP-BLOCKED" \
comment="Drop blocked RDP IPs"
# RDP rate limiting stages
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
connection-state=new src-address-list=rdp-stage2 \
action=add-src-to-address-list \
address-list=rdp-blocked address-list-timeout=24h \
comment="RDP brute-force block"
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
connection-state=new src-address-list=rdp-stage1 \
action=add-src-to-address-list \
address-list=rdp-stage2 address-list-timeout=1m \
comment="RDP stage2"
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
connection-state=new action=add-src-to-address-list \
address-list=rdp-stage1 address-list-timeout=1m \
comment="RDP stage1"
# RDP whitelist — accept (после rate limiting!)
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
src-address-list=rdp-whitelist action=accept \
comment="Allow RDP from whitelist"
# Блокируем прямой RDP (порт 3389) из интернета
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
action=drop log=yes log-prefix="RDP-DIRECT-DROP" \
comment="Block direct RDP port 3389"
# Блокируем нестандартный порт для не-whitelist
add chain=forward in-interface=ether1 protocol=tcp dst-port=47832 \
action=drop log=yes log-prefix="RDP-DENIED" \
comment="Block RDP alt port for non-whitelist"
# Список заблокированных IP
/ip/firewall/address-list/print where list=rdp-blocked
# Количество заблокированных
/ip/firewall/address-list/print count-only where list=rdp-blocked
# Whitelist
/ip/firewall/address-list/print where list=rdp-whitelist
# Все RDP-связанные записи в логе
/log/print where message~"RDP"
# Только заблокированные
/log/print where message~"RDP-BLOCKED"
# Попытки прямого подключения к 3389
/log/print where message~"RDP-DIRECT"
/ip/firewall/filter/print stats where comment~"RDP"
# С самого MikroTik (проверяем из-под другого IP через bandwidth-test или fetch)
/tool/fetch url="https://portchecker.co/check" mode=https
# Проверяем что IP попал в rdp-stage1 после первого подключения
/ip/firewall/address-list/print where list=rdp-stage1
# После третьего — должен быть в rdp-blocked
/ip/firewall/address-list/print where list=rdp-blocked
/system/logging
add topics=firewall action=remote prefix="FW" \
comment="Firewall logs to remote syslog"
/system/script
add name=rdp-alert source={
:local botToken "YOUR_BOT_TOKEN"
:local chatId "YOUR_CHAT_ID"
:local blockedCount [/ip/firewall/address-list/print count-only where list=rdp-blocked]
:if ($blockedCount > 0) do={
:local msg "RDP Alert: $blockedCount IPs blocked in last 24h"
/tool/fetch url="https://api.telegram.org/bot$botToken/sendMessage\?chat_id=$chatId&text=$msg" \
mode=https keep-result=no
}
}
/system/scheduler
add name=rdp-alert-check interval=1h on-event="/system/script/run rdp-alert"
# PowerShell на RDP-сервере
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name 'UserAuthentication' -Value 1
# НЕПРАВИЛЬНО! Accept стоит перед rate limiting
/ip/firewall/filter
add chain=forward protocol=tcp dst-port=3389 action=accept # пропускает ВСЁ
add chain=forward protocol=tcp dst-port=3389 src-address-list=rdp-blocked action=drop
/ip/firewall/filter
add chain=forward protocol=tcp dst-port=3389 src-address-list=rdp-blocked action=drop
# ... rate limiting rules ...
add chain=forward protocol=tcp dst-port=3389 action=accept
# При dst-nat 47832→3389:
# В chain=forward пакет приходит с dst-port=3389, НЕ 47832!
# ПРАВИЛЬНО: rate limit по dst-port=3389 в forward
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
connection-state=new src-address-list=rdp-stage2 \
action=add-src-to-address-list address-list=rdp-blocked \
address-list-timeout=24h
# Или используйте connection-nat-dst-port для фильтрации по оригинальному порту
/ip/firewall/raw
add chain=prerouting in-interface=ether1 protocol=tcp dst-port=47832 \
src-address-list=rdp-blocked action=drop
# НЕ ЗАБУДЬТЕ! Даже если dst-nat только на 47832, сканеры найдут 3389
/ip/firewall/filter
add chain=forward in-interface=ether1 protocol=tcp dst-port=3389 \
action=drop comment="Block standard RDP port"
# СЛАБО: 10 минут блокировки — бот просто подождёт
address-list-timeout=10m
address-list-timeout=7d
# Добавьте log ко всем drop-правилам
action=drop log=yes log-prefix="RDP-ATTEMPT"
# Убедитесь что dst-nat для RDP через WAN НЕ существует
/ip/firewall/nat/print where dst-port=3389 chain=dstnat
# Должно быть пусто!