"Что
<br />
Настроишь безопасный доступ к MikroTik CHR: новый администратор, SSH только по ключам, strong-crypto, защита от брутфорса через firewall, NTP и логирование.<br />
Дефолтный admin будет отключён. Всё проверено на реальном стенде CHR 7.22.1.<br />
<h2>Почему MikroTik CHR без защиты ломают первым</h2>
<p>Дефолтная конфигурация <a title="Установка MikroTik CHR на Proxmox: от образа до базовой защиты" href="https://it-apteka.com/ustanovka-mikrotik-chr-na-proxmox-ot-obraza-do-bazovoj-zashhity/" target="_blank" rel="noopener" data-wpil-monitor-id="1739">CHR после установки</a> — это открытая дверь. Пользователь admin известен всем сканерам в интернете. SSH на стандартном порту. Никакой защиты от перебора паролей.</p>
<p>Если CHR смотрит наружу — боты найдут его за минуты. Логи начнут пухнуть от попыток входа, а если пароль слабый — вопрос времени когда зайдут. В первой статье мы уже закрыли лишние сервисы и поставили базовый firewall. Теперь идём дальше.</p>
<p>В этой статье делаем семь вещей: меняем имя устройства, создаём отдельного администратора, настраиваем SSH по ключам, включаем strong-crypto, добавляем защиту от брутфорса, синхронизируем время и включаем логирование.</p>
<h4>Видео пошаговый скринкаст:</h4>
<h2>С чего начинаем — состояние стенда</h2>
<p>Стартуем с того места где закончили в первой статье. Проверяем:</p>
<pre><code class="language-bash">
/system identity print
/ip service print
/ip firewall filter print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
name: MikroTik
Flags: D - DYNAMIC; X - DISABLED, I - INVALID
# NAME PORT PROTO
0 X ftp 21 tcp
1 X telnet 23 tcp
3 X www 80 tcp
7 ssh 2222 tcp
11 winbox 8291 tcp
12 X api 8728 tcp
13 X api-ssl 8729 tcp
Flags: X - DISABLED, I - INVALID; D - DYNAMIC
0 ;;; accept-established-related
chain=input action=accept connection-state=established,related
1 ;;; accept-icmp
chain=input action=accept protocol=icmp
2 ;;; accept-ssh-mgmt
chain=input action=accept protocol=tcp src-address=192.168.168.0/24 dst-port=2222
3 ;;; accept-winbox-mgmt
chain=input action=accept protocol=tcp src-address=192.168.168.0/24 dst-port=8291
4 ;;; drop-all
chain=input action=drop
</code></pre>
<p>Лишние сервисы отключены, базовый firewall стоит. Поехали дальше.</p>
<h2>Смена имени устройства</h2>
<p>Дефолтное имя <a title="DynDNS: полный гайд по настройке динамического DNS на роутере, Keenetic и MikroTik — бесплатно и без боли" href="https://it-apteka.com/dyndns-polnyj-gajd-po-nastrojke-dinamicheskogo-dns-na-routere-keenetic-i-mikrotik-besplatno-i-bez-boli/" target="_blank" rel="noopener" data-wpil-monitor-id="1730">MikroTik — первый признак незащищённого роутера</a>. Меняем сразу:</p>
<pre><code class="language-bash">
/system identity set name=chr-proxmox-01
/system identity print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
name: chr-proxmox-01
</code></pre>
<p>Промпт сразу сменится на <code>[admin@chr-proxmox-01]</code>. Мелочь, но в логах сразу видно о каком устройстве речь — особенно когда роутеров несколько.</p>
<h2>Создаём нового администратора</h2>
<p>Пользователь <code>admin</code> — это первое что перебирают брутфорсеры. Создаём своего пользователя и отключаем дефолтного.</p>
<pre><code class="language-bash">
/user add name=sys0dmin password=ТВОЙ_ПАРОЛЬ group=full
/user print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Columns: NAME, GROUP, LAST-LOGGED-IN, INACTIVITY-POLICY
# NAME GROUP LAST-LOGGED-IN INACTIVITY-POLICY
;;; system default user
0 admin full 2026-04-20 05:14:45 none
1 sys0dmin full none
</code></pre>
<p>Проверяем что новый пользователь работает — до того как отключить admin:</p>
<pre><code class="language-bash">
ssh -p 2222 sys0dmin@192.168.168.29
</code></pre>
<p>Вошёл — хорошо. Теперь отключаем admin:</p>
<pre><code class="language-bash">
/user disable admin
/user print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Flags: X - DISABLED
# NAME GROUP LAST-LOGGED-IN INACTIVITY-POLICY
;;; system default user
0 X admin full 2026-04-20 05:14:45 none
1 sys0dmin full 2026-04-20 05:15:00 none
</code></pre>
"Не
<br />
RouterOS не даст удалить последнего активного пользователя группы full. Но если что-то пойдёт не так с новым пользователем — через qm terminal всегда можно включить admin обратно командой /user enable admin.<br />
<h2>Как настроить SSH по ключам на MikroTik</h2>
<p>Пароль можно подобрать. Ключ — нет. Переходим на аутентификацию по SSH ключам.</p>
<h3>Генерируем ключ на Proxmox</h3>
<p>Выполняем на <a class="wpil_keyword_link" title="Виртуализация" href="https://it-apteka.com/category/virtualise/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1742">Proxmox</a>, не на CHR:</p>
<pre><code class="language-bash">
ssh-keygen -t ed25519 -f /root/.ssh/mikrotik_key -N "" -C "proxmox-to-chr"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Generating public/private ed25519 key pair.
Your identification has been saved in /root/.ssh/mikrotik_key
Your public key has been saved in /root/.ssh/mikrotik_key.pub
The key fingerprint is:
SHA256:W40RlzYgi7trstZT6ANDmJFvh98geNXh1njmerFNl98 proxmox-to-chr
</code></pre>
<p>Почему ed25519 а не RSA. Короче ключ, быстрее аутентификация, современная криптография. RSA работает но ed25519 — правильный выбор для новых установок.</p>
<h3>Копируем публичный ключ на CHR</h3>
<pre><code class="language-bash">
scp -P 2222 /root/.ssh/mikrotik_key.pub sys0dmin@192.168.168.29:/mikrotik_key.pub
</code></pre>
<p>Проверяем что файл попал на роутер:</p>
<pre><code class="language-bash">
/file print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
# NAME TYPE SIZE LAST-MODIFIED
0 skins directory 2026-04-19 05:24:02
1 mikrotik_key.pub ssh key 96 2026-04-20 05:15:14
</code></pre>
<h3>Импортируем ключ в RouterOS</h3>
<p>Вот тут важное отличие от <a class="wpil_keyword_link" title="Linux" href="https://it-apteka.com/category/linux/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1740">Linux</a>. RouterOS не использует <code>~/.ssh/authorized_keys</code>. Ключи импортируются через команду и привязываются к конкретному пользователю:</p>
<pre><code class="language-bash">
/user ssh-keys import public-key-file=mikrotik_key.pub user=sys0dmin
</code></pre>
<p>В логах появится подтверждение:</p>
<pre><code class="language-text">
ssh,info 256bit public key imported, owner=proxmox-to-chr,
fingerprint=SHA256:W40RlzYgi7trstZT6ANDmJFvh98geNXh1njmerFNl98=
</code></pre>
<h3>Проверяем вход по ключу</h3>
<pre><code class="language-bash">
ssh -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29
</code></pre>
<p>Если зашёл без пароля — ключ работает. В логах будет:</p>
<pre><code class="language-text">
ssh,info publickey accepted for user: sys0dmin,
fingerprint: SHA256:W40RlzYgi7trstZT6ANDmJFvh98geNXh1njmerFNl98=
</code></pre>
<h2>Включаем strong-crypto для SSH</h2>
<p>По умолчанию RouterOS поддерживает старые алгоритмы шифрования для совместимости. Отключаем их:</p>
<pre><code class="language-bash">
/ip ssh set strong-crypto=yes
/ip ssh print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
ciphers: auto
forwarding-enabled: no
password-authentication: yes-if-no-key
publickey-authentication-options: none
strong-crypto: yes
host-key-size: 2048
host-key-type: rsa
</code></pre>
<p>Обрати внимание на <code>password-authentication: yes-if-no-key</code>. Это значит RouterOS разрешает пароль только если у пользователя нет ключа. У sys0dmin ключ есть — пароль больше не работает автоматически.</p>
<h2>Защита MikroTik от брутфорса через firewall</h2>
<p>Механизм простой: три неудачные попытки входа за минуту — IP блокируется на час. Реализуется через цепочку address-list в firewall.</p>
<pre class="mermaid">%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Новое TCP соединение на порт 2222"] --> B{"IP в ssh-blacklist?"}
B -->|да| C["DROP - заблокирован на 1 час"]
B -->|нет| D{"IP в ssh-stage3?"}
D -->|да| E["Добавить в ssh-blacklist на 1 час"]
D -->|нет| F{"IP в ssh-stage2?"}
F -->|да| G["Добавить в ssh-stage3 на 1 мин"]
F -->|нет| H{"IP в ssh-stage1?"}
H -->|да| I["Добавить в ssh-stage2 на 1 мин"]
H -->|нет| J["Добавить в ssh-stage1 на 1 мин"]
style C fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#dc2626
style E fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#dc2626
</pre>
<p>Добавляем правила строго в таком порядке — после существующих правил accept, но до drop-all:</p>
<pre><code class="language-bash">
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new action=add-src-to-address-list address-list=ssh-stage1 address-list-timeout=1m comment=detect-ssh-scan
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new src-address-list=ssh-stage1 action=add-src-to-address-list address-list=ssh-stage2 address-list-timeout=1m comment=blacklist-stage1
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new src-address-list=ssh-stage2 action=add-src-to-address-list address-list=ssh-stage3 address-list-timeout=1m comment=blacklist-stage2
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new src-address-list=ssh-stage3 action=add-src-to-address-list address-list=ssh-blacklist address-list-timeout=1h comment=blacklist-stage3
/ip firewall filter add chain=input protocol=tcp dst-port=2222 src-address-list=ssh-blacklist action=drop comment=drop-ssh-bruteforce
</code></pre>
<p>Финальный вид firewall filter:</p>
<pre><code class="language-text">
Flags: X - DISABLED, I - INVALID; D - DYNAMIC
# CHAIN ACTION COMMENT
0 input accept accept-established-related
1 input accept accept-icmp
2 input accept accept-ssh-mgmt
3 input accept accept-winbox-mgmt
4 input drop drop-all
5 input add-src-to-address-list detect-ssh-scan
6 input add-src-to-address-list blacklist-stage1
7 input add-src-to-address-list blacklist-stage2
8 input add-src-to-address-list blacklist-stage3
9 input drop drop-ssh-bruteforce
</code></pre>
"Правила
<br />
Это сделано намеренно. Правила брутфорса работают только для трафика из нашей подсети который уже прошёл через accept-ssh-mgmt. Для внешних адресов drop-all срабатывает раньше.<br />
<h2>Настройка NTP на MikroTik CHR</h2>
<p>Без синхронизации времени логи бесполезны. Временные метки будут врать — и когда будешь разбирать инцидент, не поймёшь когда что произошло.</p>
<pre><code class="language-bash">
/system ntp client set enabled=yes servers=pool.ntp.org
/system ntp client print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
enabled: yes
mode: unicast
servers: pool.ntp.org
vrf: main
freq-drift: 0 PPM
status: waiting
</code></pre>
<p>Статус <code>waiting</code> — нормально, CHR только что подключился к NTP серверу. Через минуту сменится на <code>synchronized</code>. Проверяем время:</p>
<pre><code class="language-bash">
/system clock print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
time: 05:16:01
date: 2026-04-20
time-zone-autodetect: yes
time-zone-name: manual
gmt-offset: +00:00
</code></pre>
<p>Если нужен другой часовой пояс — настрой вручную:</p>
<pre><code class="language-bash">
/system clock set time-zone-name=Europe/Moscow
</code></pre>
<h2>Настройка логирования в MikroTik</h2>
<p>По умолчанию RouterOS пишет info, error, warning и critical. Добавляем два важных топика — firewall события и входы пользователей:</p>
<pre><code class="language-bash">
/system logging add topics=firewall action=memory
/system logging add topics=account action=memory
/system logging print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Flags: * - DEFAULT
Columns: TOPICS, ACTION
# TOPICS ACTION
0 * info memory
1 * error memory
2 * warning memory
3 * critical echo
4 firewall memory
5 account memory
</code></pre>
<p>Смотрим логи:</p>
<pre><code class="language-bash">
/log print
</code></pre>
<p>Из реальных логов видно всю историю сессии — кто заходил, с какого IP, что менял:</p>
<pre><code class="language-text">
2026-04-20 05:14:45 system,info user sys0dmin added by ssh-cmd:admin@192.168.168.252
2026-04-20 05:15:00 system,info user admin changed by ssh-cmd:sys0dmin@192.168.168.252 (/user set admin disabled=yes)
2026-04-20 05:15:23 ssh,info 256bit public key imported, owner=proxmox-to-chr
2026-04-20 05:15:32 ssh,info publickey accepted for user: sys0dmin
2026-04-20 05:15:39 system,info ssh settings changed (/ip ssh set strong-crypto=yes)
</code></pre>
<p>Каждое действие записано с временной меткой, пользователем и командой. Для аудита — идеально.</p>
<h2>Финальный бэкап</h2>
<pre><code class="language-bash">
/system backup save name=chr-security-basic
/file print
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
# NAME TYPE SIZE LAST-MODIFIED
0 skins dir 2026-04-19 05:24:02
1 chr-services-disabled.backup backup 19.9KiB 2026-04-19 05:56:49
2 chr-initial.backup backup 19.4KiB 2026-04-19 05:50:21
3 chr-firewall-basic.backup backup 20.5KiB 2026-04-19 05:57:48
4 chr-security-basic.backup backup 21.8KiB 2026-04-20 05:16:23
</code></pre>
<p>Видна история бэкапов с первой статьи. Каждый этап зафиксирован.</p>
<h2>Таблица портов после настройки</h2>
<table>
<thead>
<tr>
<th>Сервис</th>
<th>Порт</th>
<th>Протокол</th>
<th>Статус</th>
<th>Доступ</th>
</tr>
</thead>
<tbody>
<tr>
<td>FTP</td>
<td>21</td>
<td>TCP</td>
<td>отключён</td>
<td>—</td>
</tr>
<tr>
<td>Telnet</td>
<td>23</td>
<td>TCP</td>
<td>отключён</td>
<td>—</td>
</tr>
<tr>
<td>WWW</td>
<td>80</td>
<td>TCP</td>
<td>отключён</td>
<td>—</td>
</tr>
<tr>
<td>SSH</td>
<td>2222</td>
<td>TCP</td>
<td>активен</td>
<td>192.168.168.0/24, только по ключу</td>
</tr>
<tr>
<td>Winbox</td>
<td>8291</td>
<td>TCP</td>
<td>активен</td>
<td>192.168.168.0/24</td>
</tr>
<tr>
<td>API</td>
<td>8728</td>
<td>TCP</td>
<td>отключён</td>
<td>—</td>
</tr>
<tr>
<td>API-SSL</td>
<td>8729</td>
<td>TCP</td>
<td>отключён</td>
<td>—</td>
</tr>
</tbody>
</table>
<h2>Troubleshooting</h2>
<h3>SSH по ключу не работает — Permission denied</h3>
<p>Проверь что ключ импортировался:</p>
<pre><code class="language-bash">
/user ssh-keys print
</code></pre>
<p>Если список пустой — импортируй заново. Убедись что файл ключа есть на роутере:</p>
<pre><code class="language-bash">
/file print
</code></pre>
<h3>Заблокировал себя в ssh-blacklist</h3>
<p>Подключайся через <code>qm terminal</code> и чисти список:</p>
<pre><code class="language-bash">
/ip firewall address-list remove [find list=ssh-blacklist]
</code></pre>
<h3>NTP не синхронизируется — статус waiting</h3>
<p>Подожди 2-3 минуты после включения. Если не меняется — проверь <a class="wpil_keyword_link" title="DNS" href="https://it-apteka.com/tag/dns/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1743">DNS</a>:</p>
<pre><code class="language-bash">
/ip dns print
/ping pool.ntp.org count=3
</code></pre>
<h3>Случайно удалил sys0dmin и admin отключён</h3>
<p>Только через <code>qm terminal 110</code>. В консоли CHR:</p>
<pre><code class="language-bash">
/user enable admin
/user add name=sys0dmin password=ПАРОЛЬ group=full
</code></pre>
<h3>Как проверить что вход по паролю действительно отключён</h3>
<p>Попробуй подключиться без ключа:</p>
<pre><code class="language-bash">
ssh -p 2222 -o PubkeyAuthentication=no sys0dmin@192.168.168.29
</code></pre>
<p>Должен получить <code>Permission denied</code>. Если просит пароль — значит <code>password-authentication</code> не отключён явно. Отключи:</p>
<pre><code class="language-bash">
/ip ssh set password-authentication=no
</code></pre>
<h2>FAQ по безопасности RouterOS</h2>
<h3>Как проверить кто подключён к MikroTik прямо сейчас?</h3>
<pre><code class="language-bash">
/ip service print
/user active print
</code></pre>
<h3>Как посмотреть заблокированные IP адреса?</h3>
<pre><code class="language-bash">
/ip firewall address-list print where list=ssh-blacklist
</code></pre>
<h3>Что делать если забыл пароль от sys0dmin?</h3>
<p>Подключайся через <code>qm terminal 110</code> — консоль Proxmox не требует SSH. Сбрось пароль:</p>
<pre><code class="language-bash">
/user set sys0dmin password=НОВЫЙ_ПАРОЛЬ
</code></pre>
<h3>Нужно ли отключать Winbox если им не пользуюсь?</h3>
<p>Да. Если Winbox не нужен — отключай:</p>
<pre><code class="language-bash">
/ip service disable winbox
</code></pre>
<h3>Как добавить второй SSH ключ для другого администратора?</h3>
<pre><code class="language-bash">
/user ssh-keys import public-key-file=second_key.pub user=sys0dmin
/user ssh-keys print
</code></pre>
<h2>Что дальше</h2>
<p>CHR теперь закрыт нормально. Дефолтный admin отключён, SSH работает только по ключам, брутфорсеры получат бан после трёх попыток, логи пишут кто и что делал.</p>
<p>Это вторая статья цикла по <a class="wpil_keyword_link" title="mikrotik" href="https://it-apteka.com/tag/mikrotik/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1744">MikroTik</a> CHR. Следующая — настройка <a class="wpil_keyword_link" title="Сети" href="https://it-apteka.com/category/networks/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1741">сети</a>: статический IP вместо DHCP, DNS, маршруты и NAT для выхода в интернет через CHR.</p>
"Не
<br />
Пиши в комментарии. Описывай: версию CHR, что именно делал, какую ошибку получил. Разберём.<br />
Что получишь на выходе
Настроишь безопасный доступ к MikroTik CHR: новый администратор, SSH только по ключам, strong-crypto, защита от брутфорса через firewall, NTP и логирование.
Дефолтный admin будет отключён. Всё проверено на реальном стенде CHR 7.22.1.
Почему MikroTik CHR без защиты ломают первым
Дефолтная конфигурация CHR после установки — это открытая дверь. Пользователь admin известен всем сканерам в интернете. SSH на стандартном порту. Никакой защиты от перебора паролей.
Если CHR смотрит наружу — боты найдут его за минуты. Логи начнут пухнуть от попыток входа, а если пароль слабый — вопрос времени когда зайдут. В первой статье мы уже закрыли лишние сервисы и поставили базовый firewall. Теперь идём дальше.
В этой статье делаем семь вещей: меняем имя устройства, создаём отдельного администратора, настраиваем SSH по ключам, включаем strong-crypto, добавляем защиту от брутфорса, синхронизируем время и включаем логирование.
Видео пошаговый скринкаст:
С чего начинаем — состояние стенда
Стартуем с того места где закончили в первой статье. Проверяем:
/system identity print
/ip service print
/ip firewall filter print
Результат:
name: MikroTik
Flags: D - DYNAMIC; X - DISABLED, I - INVALID
# NAME PORT PROTO
0 X ftp 21 tcp
1 X telnet 23 tcp
3 X www 80 tcp
7 ssh 2222 tcp
11 winbox 8291 tcp
12 X api 8728 tcp
13 X api-ssl 8729 tcp
Flags: X - DISABLED, I - INVALID; D - DYNAMIC
0 ;;; accept-established-related
chain=input action=accept connection-state=established,related
1 ;;; accept-icmp
chain=input action=accept protocol=icmp
2 ;;; accept-ssh-mgmt
chain=input action=accept protocol=tcp src-address=192.168.168.0/24 dst-port=2222
3 ;;; accept-winbox-mgmt
chain=input action=accept protocol=tcp src-address=192.168.168.0/24 dst-port=8291
4 ;;; drop-all
chain=input action=drop
Лишние сервисы отключены, базовый firewall стоит. Поехали дальше.
Смена имени устройства
Дефолтное имя MikroTik — первый признак незащищённого роутера. Меняем сразу:
/system identity set name=chr-proxmox-01
/system identity print
Результат:
name: chr-proxmox-01
Промпт сразу сменится на [admin@chr-proxmox-01]. Мелочь, но в логах сразу видно о каком устройстве речь — особенно когда роутеров несколько.
Создаём нового администратора
Пользователь admin — это первое что перебирают брутфорсеры. Создаём своего пользователя и отключаем дефолтного.
/user add name=sys0dmin password=ТВОЙ_ПАРОЛЬ group=full
/user print
Результат:
Columns: NAME, GROUP, LAST-LOGGED-IN, INACTIVITY-POLICY
# NAME GROUP LAST-LOGGED-IN INACTIVITY-POLICY
;;; system default user
0 admin full 2026-04-20 05:14:45 none
1 sys0dmin full none
Проверяем что новый пользователь работает — до того как отключить admin:
ssh -p 2222 sys0dmin@192.168.168.29
Вошёл — хорошо. Теперь отключаем admin:
/user disable admin
/user print
Результат:
Flags: X - DISABLED
# NAME GROUP LAST-LOGGED-IN INACTIVITY-POLICY
;;; system default user
0 X admin full 2026-04-20 05:14:45 none
1 sys0dmin full 2026-04-20 05:15:00 none
Не удаляй admin - только отключай
RouterOS не даст удалить последнего активного пользователя группы full. Но если что-то пойдёт не так с новым пользователем — через qm terminal всегда можно включить admin обратно командой /user enable admin.
Как настроить SSH по ключам на MikroTik
Пароль можно подобрать. Ключ — нет. Переходим на аутентификацию по SSH ключам.
Генерируем ключ на Proxmox
Выполняем на Proxmox, не на CHR:
ssh-keygen -t ed25519 -f /root/.ssh/mikrotik_key -N "" -C "proxmox-to-chr"
Результат:
Generating public/private ed25519 key pair.
Your identification has been saved in /root/.ssh/mikrotik_key
Your public key has been saved in /root/.ssh/mikrotik_key.pub
The key fingerprint is:
SHA256:W40RlzYgi7trstZT6ANDmJFvh98geNXh1njmerFNl98 proxmox-to-chr
Почему ed25519 а не RSA. Короче ключ, быстрее аутентификация, современная криптография. RSA работает но ed25519 — правильный выбор для новых установок.
Копируем публичный ключ на CHR
scp -P 2222 /root/.ssh/mikrotik_key.pub sys0dmin@192.168.168.29:/mikrotik_key.pub
Проверяем что файл попал на роутер:
/file print
Результат:
# NAME TYPE SIZE LAST-MODIFIED
0 skins directory 2026-04-19 05:24:02
1 mikrotik_key.pub ssh key 96 2026-04-20 05:15:14
Импортируем ключ в RouterOS
Вот тут важное отличие от Linux. RouterOS не использует ~/.ssh/authorized_keys. Ключи импортируются через команду и привязываются к конкретному пользователю:
/user ssh-keys import public-key-file=mikrotik_key.pub user=sys0dmin
В логах появится подтверждение:
ssh,info 256bit public key imported, owner=proxmox-to-chr,
fingerprint=SHA256:W40RlzYgi7trstZT6ANDmJFvh98geNXh1njmerFNl98=
Проверяем вход по ключу
ssh -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29
Если зашёл без пароля — ключ работает. В логах будет:
ssh,info publickey accepted for user: sys0dmin,
fingerprint: SHA256:W40RlzYgi7trstZT6ANDmJFvh98geNXh1njmerFNl98=
Включаем strong-crypto для SSH
По умолчанию RouterOS поддерживает старые алгоритмы шифрования для совместимости. Отключаем их:
/ip ssh set strong-crypto=yes
/ip ssh print
Результат:
ciphers: auto
forwarding-enabled: no
password-authentication: yes-if-no-key
publickey-authentication-options: none
strong-crypto: yes
host-key-size: 2048
host-key-type: rsa
Обрати внимание на password-authentication: yes-if-no-key. Это значит RouterOS разрешает пароль только если у пользователя нет ключа. У sys0dmin ключ есть — пароль больше не работает автоматически.
Защита MikroTik от брутфорса через firewall
Механизм простой: три неудачные попытки входа за минуту — IP блокируется на час. Реализуется через цепочку address-list в firewall.
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Новое TCP соединение на порт 2222"] --> B{"IP в ssh-blacklist?"}
B -->|да| C["DROP - заблокирован на 1 час"]
B -->|нет| D{"IP в ssh-stage3?"}
D -->|да| E["Добавить в ssh-blacklist на 1 час"]
D -->|нет| F{"IP в ssh-stage2?"}
F -->|да| G["Добавить в ssh-stage3 на 1 мин"]
F -->|нет| H{"IP в ssh-stage1?"}
H -->|да| I["Добавить в ssh-stage2 на 1 мин"]
H -->|нет| J["Добавить в ssh-stage1 на 1 мин"]
style C fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#dc2626
style E fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#dc2626
Добавляем правила строго в таком порядке — после существующих правил accept, но до drop-all:
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new action=add-src-to-address-list address-list=ssh-stage1 address-list-timeout=1m comment=detect-ssh-scan
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new src-address-list=ssh-stage1 action=add-src-to-address-list address-list=ssh-stage2 address-list-timeout=1m comment=blacklist-stage1
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new src-address-list=ssh-stage2 action=add-src-to-address-list address-list=ssh-stage3 address-list-timeout=1m comment=blacklist-stage2
/ip firewall filter add chain=input protocol=tcp dst-port=2222 connection-state=new src-address-list=ssh-stage3 action=add-src-to-address-list address-list=ssh-blacklist address-list-timeout=1h comment=blacklist-stage3
/ip firewall filter add chain=input protocol=tcp dst-port=2222 src-address-list=ssh-blacklist action=drop comment=drop-ssh-bruteforce
Финальный вид firewall filter:
Flags: X - DISABLED, I - INVALID; D - DYNAMIC
# CHAIN ACTION COMMENT
0 input accept accept-established-related
1 input accept accept-icmp
2 input accept accept-ssh-mgmt
3 input accept accept-winbox-mgmt
4 input drop drop-all
5 input add-src-to-address-list detect-ssh-scan
6 input add-src-to-address-list blacklist-stage1
7 input add-src-to-address-list blacklist-stage2
8 input add-src-to-address-list blacklist-stage3
9 input drop drop-ssh-bruteforce
Правила detect-ssh-scan стоят после drop-all
Это сделано намеренно. Правила брутфорса работают только для трафика из нашей подсети который уже прошёл через accept-ssh-mgmt. Для внешних адресов drop-all срабатывает раньше.
Настройка NTP на MikroTik CHR
Без синхронизации времени логи бесполезны. Временные метки будут врать — и когда будешь разбирать инцидент, не поймёшь когда что произошло.
/system ntp client set enabled=yes servers=pool.ntp.org
/system ntp client print
Результат:
enabled: yes
mode: unicast
servers: pool.ntp.org
vrf: main
freq-drift: 0 PPM
status: waiting
Статус waiting — нормально, CHR только что подключился к NTP серверу. Через минуту сменится на synchronized. Проверяем время:
/system clock print
Результат:
time: 05:16:01
date: 2026-04-20
time-zone-autodetect: yes
time-zone-name: manual
gmt-offset: +00:00
Если нужен другой часовой пояс — настрой вручную:
/system clock set time-zone-name=Europe/Moscow
Настройка логирования в MikroTik
По умолчанию RouterOS пишет info, error, warning и critical. Добавляем два важных топика — firewall события и входы пользователей:
/system logging add topics=firewall action=memory
/system logging add topics=account action=memory
/system logging print
Результат:
Flags: * - DEFAULT
Columns: TOPICS, ACTION
# TOPICS ACTION
0 * info memory
1 * error memory
2 * warning memory
3 * critical echo
4 firewall memory
5 account memory
Смотрим логи:
/log print
Из реальных логов видно всю историю сессии — кто заходил, с какого IP, что менял:
2026-04-20 05:14:45 system,info user sys0dmin added by ssh-cmd:admin@192.168.168.252
2026-04-20 05:15:00 system,info user admin changed by ssh-cmd:sys0dmin@192.168.168.252 (/user set admin disabled=yes)
2026-04-20 05:15:23 ssh,info 256bit public key imported, owner=proxmox-to-chr
2026-04-20 05:15:32 ssh,info publickey accepted for user: sys0dmin
2026-04-20 05:15:39 system,info ssh settings changed (/ip ssh set strong-crypto=yes)
Каждое действие записано с временной меткой, пользователем и командой. Для аудита — идеально.
Финальный бэкап
/system backup save name=chr-security-basic
/file print
Результат:
# NAME TYPE SIZE LAST-MODIFIED
0 skins dir 2026-04-19 05:24:02
1 chr-services-disabled.backup backup 19.9KiB 2026-04-19 05:56:49
2 chr-initial.backup backup 19.4KiB 2026-04-19 05:50:21
3 chr-firewall-basic.backup backup 20.5KiB 2026-04-19 05:57:48
4 chr-security-basic.backup backup 21.8KiB 2026-04-20 05:16:23
Видна история бэкапов с первой статьи. Каждый этап зафиксирован.
Таблица портов после настройки
| Сервис |
Порт |
Протокол |
Статус |
Доступ |
| FTP |
21 |
TCP |
отключён |
— |
| Telnet |
23 |
TCP |
отключён |
— |
| WWW |
80 |
TCP |
отключён |
— |
| SSH |
2222 |
TCP |
активен |
192.168.168.0/24, только по ключу |
| Winbox |
8291 |
TCP |
активен |
192.168.168.0/24 |
| API |
8728 |
TCP |
отключён |
— |
| API-SSL |
8729 |
TCP |
отключён |
— |
Troubleshooting
SSH по ключу не работает — Permission denied
Проверь что ключ импортировался:
/user ssh-keys print
Если список пустой — импортируй заново. Убедись что файл ключа есть на роутере:
/file print
Заблокировал себя в ssh-blacklist
Подключайся через qm terminal и чисти список:
/ip firewall address-list remove [find list=ssh-blacklist]
NTP не синхронизируется — статус waiting
Подожди 2-3 минуты после включения. Если не меняется — проверь DNS:
/ip dns print
/ping pool.ntp.org count=3
Случайно удалил sys0dmin и admin отключён
Только через qm terminal 110. В консоли CHR:
/user enable admin
/user add name=sys0dmin password=ПАРОЛЬ group=full
Как проверить что вход по паролю действительно отключён
Попробуй подключиться без ключа:
ssh -p 2222 -o PubkeyAuthentication=no sys0dmin@192.168.168.29
Должен получить Permission denied. Если просит пароль — значит password-authentication не отключён явно. Отключи:
/ip ssh set password-authentication=no
FAQ по безопасности RouterOS
Как проверить кто подключён к MikroTik прямо сейчас?
/ip service print
/user active print
Как посмотреть заблокированные IP адреса?
/ip firewall address-list print where list=ssh-blacklist
Что делать если забыл пароль от sys0dmin?
Подключайся через qm terminal 110 — консоль Proxmox не требует SSH. Сбрось пароль:
/user set sys0dmin password=НОВЫЙ_ПАРОЛЬ
Нужно ли отключать Winbox если им не пользуюсь?
Да. Если Winbox не нужен — отключай:
/ip service disable winbox
Как добавить второй SSH ключ для другого администратора?
/user ssh-keys import public-key-file=second_key.pub user=sys0dmin
/user ssh-keys print
Что дальше
CHR теперь закрыт нормально. Дефолтный admin отключён, SSH работает только по ключам, брутфорсеры получат бан после трёх попыток, логи пишут кто и что делал.
Это вторая статья цикла по MikroTik CHR. Следующая — настройка сети: статический IP вместо DHCP, DNS, маршруты и NAT для выхода в интернет через CHR.
Не заработало - разберёмся
Пиши в комментарии. Описывай: версию CHR, что именно делал, какую ошибку получил. Разберём.