"Что
<br />
Настроишь полноценную сеть на <a class="wpil_keyword_link" href="https://it-apteka.com/tag/mikrotik/" target="_blank" rel="noopener" title="mikrotik" data-wpil-keyword-link="linked" data-wpil-monitor-id="2087">MikroTik</a> CHR: статический IP вместо DHCP, дефолтный маршрут, DNS, DHCP сервер для LAN клиентов и SNAT для выхода в интернет. Клиенты за CHR будут получать адреса автоматически и ходить в интернет через роутер. Всё проверено на реальном стенде CHR 7.22.1 + Proxmox 9.1.4.<br />
<h2>Архитектура стенда</h2>
<p>В этой статье строим полноценную двухинтерфейсную схему. CHR получает второй сетевой интерфейс и становится настоящим шлюзом для LAN сети.</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["Интернет"] --> B["Proxmox vmbr0\n192.168.168.0/24"]
B --> C["CHR ether1\n192.168.168.29/24 - WAN"]
C --> D["CHR ether2\n192.168.88.1/24 - LAN"]
D --> E["vmbr1 - internal bridge"]
E --> F["LXC Ubuntu\n192.168.88.254/24 - клиент"]
style A fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b
style B fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style C fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style D fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style E fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b
style F fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
</pre>
<p>Два интерфейса — стандартная схема для роутера. ether1 смотрит наружу в сеть <a class="wpil_keyword_link" href="https://it-apteka.com/category/virtualise/" target="_blank" rel="noopener" title="Виртуализация" data-wpil-keyword-link="linked" data-wpil-monitor-id="2089">Proxmox</a> и дальше в интернет. ether2 смотрит внутрь — это LAN для клиентов. SNAT транслирует адреса клиентов в IP ether1 при выходе наружу.</p>
<h2>Системные требования</h2>
<table>
<thead>
<tr>
<th>Компонент</th>
<th>Версия</th>
</tr>
</thead>
<tbody>
<tr>
<td>Proxmox VE</td>
<td>9.1.4</td>
</tr>
<tr>
<td>MikroTik CHR</td>
<td>7.22.1 stable</td>
</tr>
<tr>
<td>Состояние CHR</td>
<td>после статьи 2 — <a class="wpil_keyword_link" href="https://it-apteka.com/category/security/" target="_blank" rel="noopener" title="Безопасность" data-wpil-keyword-link="linked" data-wpil-monitor-id="2088">безопасность</a> настроена</td>
</tr>
<tr>
<td>LXC шаблон</td>
<td>ubuntu-24.04-standard_24.04-2_amd64</td>
</tr>
</tbody>
</table>
<h2>Часть 1: Подготовка Proxmox</h2>
<h4>Видео пошаговый скринкаст:</h4>
<h3>Шаг 1. Скачиваем шаблон Ubuntu для LXC</h3>
<p>Нам понадобится LXC контейнер как клиент в LAN <a title="DHCP Snooping — что это такое и как защитить сеть от Rogue DHCP сервера" href="https://it-apteka.com/dhcp-snooping-chto-jeto-takoe-i-kak-zashhitit-set-ot-rogue-dhcp-servera-2/" target="_blank" rel="noopener" data-wpil-monitor-id="2063">сети — чтобы проверить что DHCP</a> и NAT работают на реальном трафике. Скачиваем шаблон заранее:</p>
<pre><code class="language-bash">
pveam update
pveam download local ubuntu-24.04-standard_24.04-2_amd64.tar.zst
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
update successful
downloading http://download.proxmox.com/images/system/ubuntu-24.04-standard_24.04-2_amd64.tar.zst
calculating checksum of existing file...OK, got correct file already, no need to download
</code></pre>
<h3>Шаг 2. Создаём внутренний bridge vmbr1</h3>
<p>vmbr1 — это изолированная LAN сеть внутри Proxmox. Без физического интерфейса — только виртуальный bridge. Через него CHR и LXC контейнер будут общаться между собой.</p>
<pre><code class="language-bash">
cat >> /etc/network/interfaces << 'EOF'
auto vmbr1
iface vmbr1 inet static
address 0.0.0.0
bridge-ports none
bridge-stp off
bridge-fd 0
bridge-vlan-aware no
EOF
ifup vmbr1
ip link show vmbr1
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
162: vmbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/ether d6:79:5b:2b:1b:3b brd ff:ff:ff:ff:ff:ff
</code></pre>
<p>Bridge поднялся. address 0.0.0.0 — намеренно. Proxmox не получает IP в этой сети — она только для VM и контейнеров.</p>
<h3>Шаг 3. Добавляем второй интерфейс в CHR VM</h3>
<pre><code class="language-bash">
qm set 110 --net1 virtio,bridge=vmbr1
qm reboot 110
sleep 20
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/interface print"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Flags: R - RUNNING
Columns: NAME, TYPE, ACTUAL-MTU, MAC-ADDRESS
# NAME TYPE ACTUAL-MTU MAC-ADDRESS
0 R ether1 ether 1500 BC:24:11:2B:B9:99
1 R ether2 ether 1500 BC:24:11:BD:08:E9
2 R lo loopback 65536 00:00:00:00:00:00
</code></pre>
<p>CHR увидел новый интерфейс как ether2. Оба запущены.</p>
"Если
<br />
RouterOS запоминает MAC адреса интерфейсов. Если VM пересоздавалась или интерфейс добавлялся повторно — CHR назначит следующий номер. Исправляется переименованием: /interface set ether3 name=ether2<br />
<h2>Часть 2: Настройка сети на CHR</h2>
<h3>Шаг 4. Статический IP на ether1</h3>
<p>Роутер должен иметь постоянный адрес — DHCP для шлюза это плохая практика. Убираем DHCP клиент и сразу назначаем статику в одной SSH сессии.</p>
"Почему
<br />
Если сначала удалить DHCP клиент и только потом добавить статику — SSH отвалится сразу после удаления DHCP. CHR потеряет IP раньше чем получит статический. Точка с запятой между командами выполняет их в одной сессии без разрыва.<br />
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-client remove [find interface=ether1]; /ip address add address=192.168.168.29/24 interface=ether1"
</code></pre>
<p>Проверяем:</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/ip address print"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Columns: ADDRESS, NETWORK, INTERFACE, VRF
# ADDRESS NETWORK INTERFACE VRF
0 192.168.168.29/24 192.168.168.0 ether1 main
</code></pre>
<h3>Шаг 5. Дефолтный маршрут и DNS</h3>
<p>После удаления DHCP клиента CHR потерял маршрут по умолчанию. Прописываем вручную:</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip route add dst-address=0.0.0.0/0 gateway=192.168.168.1"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dns set servers=8.8.8.8,8.8.4.4 allow-remote-requests=yes"
</code></pre>
<p>Проверяем маршруты:</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/ip route print"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Flags: D - DYNAMIC; A - ACTIVE; c - CONNECT, s - STATIC
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
# DST-ADDRESS GATEWAY ROUTING-TABLE DISTANCE
0 As 0.0.0.0/0 192.168.168.1 main 1
DAc 192.168.168.0/24 ether1 main 0
</code></pre>
<p>Флаг <code>As</code> — Active Static. Маршрут активен и прописан руками. <code>allow-remote-requests=yes</code> на <a class="wpil_keyword_link" href="https://it-apteka.com/tag/dns/" target="_blank" rel="noopener" title="DNS" data-wpil-keyword-link="linked" data-wpil-monitor-id="2090">DNS</a> — CHR будет отвечать на DNS запросы от клиентов в LAN.</p>
<h3>Шаг 6. Проверяем связь CHR с интернетом</h3>
<p>Прежде чем настраивать NAT для клиентов — убеждаемся что сам роутер ходит наружу:</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/ping 8.8.8.8 count=3"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
SEQ HOST SIZE TTL TIME
0 8.8.8.8 56 104 36ms586us
1 8.8.8.8 56 104 36ms397us
2 8.8.8.8 56 104 36ms516us
sent=3 received=3 packet-loss=0%
</code></pre>
<p>CHR видит интернет. Теперь настраиваем LAN.</p>
<h3>Шаг 7. IP адрес на ether2</h3>
<p>ether2 получает первый адрес подсети — он будет шлюзом для всех клиентов:</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip address add address=192.168.88.1/24 interface=ether2"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip address print"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Columns: ADDRESS, NETWORK, INTERFACE, VRF
# ADDRESS NETWORK INTERFACE VRF
0 192.168.168.29/24 192.168.168.0 ether1 main
1 192.168.88.1/24 192.168.88.0 ether2 main
</code></pre>
<h2>Часть 3: DHCP сервер для LAN</h2>
<h3>Шаг 8. Настраиваем DHCP сервер</h3>
<p>Три шага: создаём пул адресов, описываем сеть, создаём сервер:</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip pool add name=lan-pool ranges=192.168.88.10-192.168.88.254"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server network add address=192.168.88.0/24 gateway=192.168.88.1 dns-server=8.8.8.8,8.8.4.4"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server add name=lan-dhcp interface=ether2 address-pool=lan-pool disabled=no"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server print"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Columns: NAME, INTERFACE, ADDRESS-POOL, LEASE-TIME
# NAME INTERFACE ADDRESS-POOL LEASE-TIME
0 lan-dhcp ether2 lan-pool 30m
</code></pre>
<p>DHCP сервер запущен на ether2. Пул от .10 до .254 — адреса .1 до .9 оставляем для статических назначений если понадобится.</p>
<h2>Часть 4: SNAT и firewall</h2>
<h3>Шаг 9. Настраиваем SNAT</h3>
<p>SNAT против masquerade — в чём разница. Masquerade определяет исходящий IP динамически на каждый пакет — удобно когда внешний IP меняется. SNAT использует фиксированный адрес — работает быстрее потому что не делает лишних вычислений. У нас статический IP на ether1 — берём SNAT.</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 action=src-nat to-addresses=192.168.168.29 out-interface=ether1 comment=snat-lan"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall nat print"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Flags: X - DISABLED, I - INVALID; D - DYNAMIC
0 ;;; snat-lan
chain=srcnat action=src-nat to-addresses=192.168.168.29
src-address=192.168.88.0/24 out-interface=ether1
</code></pre>
<h3>Шаг 10. Разрешаем forward трафик</h3>
<p>По умолчанию RouterOS не пропускает трафик между интерфейсами — нужны явные правила в chain forward. Добавляем два: разрешаем трафик из LAN наружу и разрешаем ответы обратно:</p>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall filter add chain=forward src-address=192.168.88.0/24 action=accept comment=allow-lan-forward"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall filter add chain=forward connection-state=established,related action=accept comment=allow-forward-established"
</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 detect-ssh-scan
6 input add-src blacklist-stage1
7 input add-src blacklist-stage2
8 input add-src blacklist-stage3
9 input drop drop-ssh-bruteforce
10 forward accept allow-lan-forward
11 forward accept allow-forward-established
</code></pre>
<h2>Часть 5: Проверка на клиенте</h2>
<h3>Шаг 11. Создаём LXC контейнер</h3>
<p>Ubuntu 24.04 как клиент в LAN сети. Подключаем на vmbr1, IP получает по DHCP:</p>
<pre><code class="language-bash">
CTID=$(pvesh get /cluster/nextid)
pct create $CTID local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst \
--hostname lan-client \
--memory 256 \
--rootfs local-lvm:2 \
--net0 name=eth0,bridge=vmbr1,ip=dhcp \
--password test1234 \
--unprivileged 1 \
--start 1
sleep 15
pct exec $CTID -- ip addr show eth0
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
2: eth0@if166: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
link/ether bc:24:11:c5:3c:5a brd ff:ff:ff:ff:ff:ff
inet 192.168.88.254/24 metric 1024 brd 192.168.88.255 scope global dynamic eth0
valid_lft 1786sec preferred_lft 1786sec
</code></pre>
<p>Клиент получил <code>192.168.88.254</code> из пула CHR. Адрес динамический — флаг <code>dynamic</code>.</p>
<h3>Шаг 12. Проверяем DHCP lease на CHR</h3>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server lease print"
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
Flags: D - DYNAMIC
Columns: ADDRESS, MAC-ADDRESS, HOST-NAME, SERVER, STATUS, LAST-SEEN
# ADDRESS MAC-ADDRESS HOST-NAME SERVER STATUS LAST-SEEN
0 D 192.168.88.254 BC:24:11:C5:3C:5A lan-client lan-dhcp bound 22s
</code></pre>
<p>CHR видит клиента — MAC адрес, hostname, статус bound. Lease активен.</p>
<h3>Шаг 13. Проверяем интернет с клиента</h3>
<p>Пингуем сначала IP — проверяем SNAT. Потом домен — проверяем DNS:</p>
<pre><code class="language-bash">
pct exec 111 -- ping -c 3 8.8.8.8
pct exec 111 -- ping -c 3 google.com
</code></pre>
<p>Результат:</p>
<pre><code class="language-text">
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=103 time=37.3 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=103 time=36.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=103 time=38.1 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, packet-loss=0%
PING google.com (74.125.131.102) 56(84) bytes of data.
64 bytes from lu-in-f102.1e100.net: icmp_seq=1 ttl=103 time=36.4 ms
64 bytes from lu-in-f102.1e100.net: icmp_seq=2 ttl=103 time=37.4 ms
64 bytes from lu-in-f102.1e100.net: icmp_seq=3 ttl=103 time=37.5 ms
--- google.com ping statistics ---
3 packets transmitted, 3 received, packet-loss=0%
</code></pre>
<p>SNAT работает — пакеты идут наружу. DNS резолвится — CHR отвечает на запросы клиентов. Потери нулевые.</p>
<h3>Шаг 14. Финальный бэкап</h3>
<pre><code class="language-bash">
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/system backup save name=chr-nat-dhcp"
</code></pre>
<h2>Таблица портов и интерфейсов</h2>
<table>
<thead>
<tr>
<th>Интерфейс</th>
<th>IP</th>
<th>Сеть</th>
<th>Назначение</th>
</tr>
</thead>
<tbody>
<tr>
<td>ether1</td>
<td>192.168.168.29/24</td>
<td>192.168.168.0/24</td>
<td>WAN — выход в интернет</td>
</tr>
<tr>
<td>ether2</td>
<td>192.168.88.1/24</td>
<td>192.168.88.0/24</td>
<td>LAN — шлюз для клиентов</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Параметр</th>
<th>Значение</th>
</tr>
</thead>
<tbody>
<tr>
<td>DHCP пул</td>
<td>192.168.88.10 — 192.168.88.254</td>
</tr>
<tr>
<td>Шлюз для клиентов</td>
<td>192.168.88.1</td>
</tr>
<tr>
<td>DNS для клиентов</td>
<td>8.8.8.8, 8.8.4.4</td>
</tr>
<tr>
<td>SNAT to-address</td>
<td>192.168.168.29</td>
</tr>
<tr>
<td>Дефолтный шлюз CHR</td>
<td>192.168.168.1</td>
</tr>
</tbody>
</table>
<h2>Troubleshooting</h2>
<h3>После удаления DHCP клиента SSH отвалился</h3>
<p>Подключайся через консоль Proxmox и назначай статику вручную:</p>
<pre><code class="language-bash">
qm terminal 110
</code></pre>
<p>В консоли CHR:</p>
<pre><code class="language-bash">
/ip address add address=192.168.168.29/24 interface=ether1
/ip route add dst-address=0.0.0.0/0 gateway=192.168.168.1
</code></pre>
<h3>LXC контейнер не получает IP по DHCP</h3>
<p>Проверь что DHCP сервер запущен на правильном интерфейсе:</p>
<pre><code class="language-bash">
/ip dhcp-server print
/ip dhcp-server network print
</code></pre>
<p>Проверь что ether2 имеет IP:</p>
<pre><code class="language-bash">
/ip address print
</code></pre>
<p>Если ether2 без адреса — DHCP сервер не знает из какой подсети выдавать адреса.</p>
<h3>Клиент получил IP но интернета нет</h3>
<p>Проверяем по шагам. Сначала пинг шлюза:</p>
<pre><code class="language-bash">
pct exec 111 -- ping -c 3 192.168.88.1
</code></pre>
<p>Если не пингуется — проблема в bridge или интерфейсе ether2. Если пингуется — проверяем SNAT:</p>
<pre><code class="language-bash">
/ip firewall nat print
</code></pre>
<p>Проверяем правила forward:</p>
<pre><code class="language-bash">
/ip firewall filter print where chain=forward
</code></pre>
<h3>Появился ether3 вместо ether2</h3>
<p>RouterOS запомнил MAC от предыдущего интерфейса. Переименовываем:</p>
<pre><code class="language-bash">
/interface set ether3 name=ether2
</code></pre>
<h3>Как проверить что SNAT работает</h3>
<p>Смотрим счётчики пакетов на правиле — они должны расти при активном трафике:</p>
<pre><code class="language-bash">
/ip firewall nat print stats where comment=snat-lan
</code></pre>
<h2>FAQ</h2>
<h3>Чем SNAT отличается от masquerade?</h3>
<p>Masquerade — это частный случай SNAT где исходящий IP определяется автоматически по интерфейсу. Удобно когда IP меняется — например при динамическом WAN. SNAT требует указать конкретный адрес явно, зато работает быстрее — не нужно вычислять IP на каждый пакет. При статическом WAN IP всегда используй SNAT.</p>
<h3>Почему пул начинается с .10 а не с .2?</h3>
<p>Адреса .1-.9 оставляем для статических назначений — принтеры, камеры, серверы которым нужен постоянный IP. Так не придётся делать статические резервации в DHCP для каждого такого устройства.</p>
<h3>Как назначить конкретный IP определённому клиенту?</h3>
<p>Через статическую привязку по MAC в DHCP:</p>
<pre><code class="language-bash">
/ip dhcp-server lease add address=192.168.88.50 mac-address=BC:24:11:C5:3C:5A server=lan-dhcp
</code></pre>
<h3>Как посмотреть кто сейчас в сети?</h3>
<pre><code class="language-bash">
/ip dhcp-server lease print where status=bound
</code></pre>
<h3>Как удалить vmbr1 если он больше не нужен?</h3>
<pre><code class="language-bash">
ifdown vmbr1
sed -i '/^auto vmbr1/,/^$/d' /etc/network/interfaces
</code></pre>
<h2>Что дальше</h2>
<p>Стенд теперь полноценный — CHR маршрутизирует трафик между двумя сетями, раздаёт адреса по DHCP и транслирует их через SNAT при выходе в интернет. Это базовая схема которая используется в большинстве реальных установок.</p>
<p>Следующая статья цикла — <a title="Безопасность MikroTik CHR: базовая настройка SSH, логов и защиты от брутфорса" href="https://it-apteka.com/bezopasnost-mikrotik-chr-bazovaja-nastrojka-ssh-logov-i-zashhity-ot-brutforsa/" target="_blank" rel="noopener" data-wpil-monitor-id="2064">настройка VPN на MikroTik CHR</a>. Поднимем WireGuard туннель для безопасного удалённого доступа в LAN сеть.</p>
"Не
<br />
Пиши в комментарии. Описывай: версию <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="2065">CHR и Proxmox</a>, что именно делал, какую ошибку получил. Разберём.<br />
Что получишь на выходе
Настроишь полноценную сеть на
MikroTik CHR: статический IP вместо DHCP, дефолтный маршрут, DNS, DHCP сервер для LAN клиентов и SNAT для выхода в интернет. Клиенты за CHR будут получать адреса автоматически и ходить в интернет через роутер. Всё проверено на реальном стенде CHR 7.22.1 + Proxmox 9.1.4.
Архитектура стенда
В этой статье строим полноценную двухинтерфейсную схему. CHR получает второй сетевой интерфейс и становится настоящим шлюзом для LAN сети.
%%{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["Интернет"] --> B["Proxmox vmbr0\n192.168.168.0/24"]
B --> C["CHR ether1\n192.168.168.29/24 - WAN"]
C --> D["CHR ether2\n192.168.88.1/24 - LAN"]
D --> E["vmbr1 - internal bridge"]
E --> F["LXC Ubuntu\n192.168.88.254/24 - клиент"]
style A fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b
style B fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style C fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style D fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style E fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b
style F fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
Два интерфейса — стандартная схема для роутера. ether1 смотрит наружу в сеть Proxmox и дальше в интернет. ether2 смотрит внутрь — это LAN для клиентов. SNAT транслирует адреса клиентов в IP ether1 при выходе наружу.
Системные требования
| Компонент |
Версия |
| Proxmox VE |
9.1.4 |
| MikroTik CHR |
7.22.1 stable |
| Состояние CHR |
после статьи 2 — безопасность настроена |
| LXC шаблон |
ubuntu-24.04-standard_24.04-2_amd64 |
Часть 1: Подготовка Proxmox
Видео пошаговый скринкаст:
Шаг 1. Скачиваем шаблон Ubuntu для LXC
Нам понадобится LXC контейнер как клиент в LAN сети — чтобы проверить что DHCP и NAT работают на реальном трафике. Скачиваем шаблон заранее:
pveam update
pveam download local ubuntu-24.04-standard_24.04-2_amd64.tar.zst
Результат:
update successful
downloading http://download.proxmox.com/images/system/ubuntu-24.04-standard_24.04-2_amd64.tar.zst
calculating checksum of existing file...OK, got correct file already, no need to download
Шаг 2. Создаём внутренний bridge vmbr1
vmbr1 — это изолированная LAN сеть внутри Proxmox. Без физического интерфейса — только виртуальный bridge. Через него CHR и LXC контейнер будут общаться между собой.
cat >> /etc/network/interfaces << 'EOF'
auto vmbr1
iface vmbr1 inet static
address 0.0.0.0
bridge-ports none
bridge-stp off
bridge-fd 0
bridge-vlan-aware no
EOF
ifup vmbr1
ip link show vmbr1
Результат:
162: vmbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/ether d6:79:5b:2b:1b:3b brd ff:ff:ff:ff:ff:ff
Bridge поднялся. address 0.0.0.0 — намеренно. Proxmox не получает IP в этой сети — она только для VM и контейнеров.
Шаг 3. Добавляем второй интерфейс в CHR VM
qm set 110 --net1 virtio,bridge=vmbr1
qm reboot 110
sleep 20
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/interface print"
Результат:
Flags: R - RUNNING
Columns: NAME, TYPE, ACTUAL-MTU, MAC-ADDRESS
# NAME TYPE ACTUAL-MTU MAC-ADDRESS
0 R ether1 ether 1500 BC:24:11:2B:B9:99
1 R ether2 ether 1500 BC:24:11:BD:08:E9
2 R lo loopback 65536 00:00:00:00:00:00
CHR увидел новый интерфейс как ether2. Оба запущены.
Если появился ether3 вместо ether2
RouterOS запоминает MAC адреса интерфейсов. Если VM пересоздавалась или интерфейс добавлялся повторно — CHR назначит следующий номер. Исправляется переименованием: /interface set ether3 name=ether2
Часть 2: Настройка сети на CHR
Шаг 4. Статический IP на ether1
Роутер должен иметь постоянный адрес — DHCP для шлюза это плохая практика. Убираем DHCP клиент и сразу назначаем статику в одной SSH сессии.
Почему обе команды в одной сессии
Если сначала удалить DHCP клиент и только потом добавить статику — SSH отвалится сразу после удаления DHCP. CHR потеряет IP раньше чем получит статический. Точка с запятой между командами выполняет их в одной сессии без разрыва.
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-client remove [find interface=ether1]; /ip address add address=192.168.168.29/24 interface=ether1"
Проверяем:
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/ip address print"
Результат:
Columns: ADDRESS, NETWORK, INTERFACE, VRF
# ADDRESS NETWORK INTERFACE VRF
0 192.168.168.29/24 192.168.168.0 ether1 main
Шаг 5. Дефолтный маршрут и DNS
После удаления DHCP клиента CHR потерял маршрут по умолчанию. Прописываем вручную:
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip route add dst-address=0.0.0.0/0 gateway=192.168.168.1"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dns set servers=8.8.8.8,8.8.4.4 allow-remote-requests=yes"
Проверяем маршруты:
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/ip route print"
Результат:
Flags: D - DYNAMIC; A - ACTIVE; c - CONNECT, s - STATIC
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
# DST-ADDRESS GATEWAY ROUTING-TABLE DISTANCE
0 As 0.0.0.0/0 192.168.168.1 main 1
DAc 192.168.168.0/24 ether1 main 0
Флаг As — Active Static. Маршрут активен и прописан руками. allow-remote-requests=yes на DNS — CHR будет отвечать на DNS запросы от клиентов в LAN.
Шаг 6. Проверяем связь CHR с интернетом
Прежде чем настраивать NAT для клиентов — убеждаемся что сам роутер ходит наружу:
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 "/ping 8.8.8.8 count=3"
Результат:
SEQ HOST SIZE TTL TIME
0 8.8.8.8 56 104 36ms586us
1 8.8.8.8 56 104 36ms397us
2 8.8.8.8 56 104 36ms516us
sent=3 received=3 packet-loss=0%
CHR видит интернет. Теперь настраиваем LAN.
Шаг 7. IP адрес на ether2
ether2 получает первый адрес подсети — он будет шлюзом для всех клиентов:
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip address add address=192.168.88.1/24 interface=ether2"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip address print"
Результат:
Columns: ADDRESS, NETWORK, INTERFACE, VRF
# ADDRESS NETWORK INTERFACE VRF
0 192.168.168.29/24 192.168.168.0 ether1 main
1 192.168.88.1/24 192.168.88.0 ether2 main
Часть 3: DHCP сервер для LAN
Шаг 8. Настраиваем DHCP сервер
Три шага: создаём пул адресов, описываем сеть, создаём сервер:
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip pool add name=lan-pool ranges=192.168.88.10-192.168.88.254"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server network add address=192.168.88.0/24 gateway=192.168.88.1 dns-server=8.8.8.8,8.8.4.4"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server add name=lan-dhcp interface=ether2 address-pool=lan-pool disabled=no"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server print"
Результат:
Columns: NAME, INTERFACE, ADDRESS-POOL, LEASE-TIME
# NAME INTERFACE ADDRESS-POOL LEASE-TIME
0 lan-dhcp ether2 lan-pool 30m
DHCP сервер запущен на ether2. Пул от .10 до .254 — адреса .1 до .9 оставляем для статических назначений если понадобится.
Часть 4: SNAT и firewall
Шаг 9. Настраиваем SNAT
SNAT против masquerade — в чём разница. Masquerade определяет исходящий IP динамически на каждый пакет — удобно когда внешний IP меняется. SNAT использует фиксированный адрес — работает быстрее потому что не делает лишних вычислений. У нас статический IP на ether1 — берём SNAT.
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 action=src-nat to-addresses=192.168.168.29 out-interface=ether1 comment=snat-lan"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall nat print"
Результат:
Flags: X - DISABLED, I - INVALID; D - DYNAMIC
0 ;;; snat-lan
chain=srcnat action=src-nat to-addresses=192.168.168.29
src-address=192.168.88.0/24 out-interface=ether1
Шаг 10. Разрешаем forward трафик
По умолчанию RouterOS не пропускает трафик между интерфейсами — нужны явные правила в chain forward. Добавляем два: разрешаем трафик из LAN наружу и разрешаем ответы обратно:
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall filter add chain=forward src-address=192.168.88.0/24 action=accept comment=allow-lan-forward"
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip firewall filter add chain=forward connection-state=established,related action=accept comment=allow-forward-established"
Финальный вид 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 detect-ssh-scan
6 input add-src blacklist-stage1
7 input add-src blacklist-stage2
8 input add-src blacklist-stage3
9 input drop drop-ssh-bruteforce
10 forward accept allow-lan-forward
11 forward accept allow-forward-established
Часть 5: Проверка на клиенте
Шаг 11. Создаём LXC контейнер
Ubuntu 24.04 как клиент в LAN сети. Подключаем на vmbr1, IP получает по DHCP:
CTID=$(pvesh get /cluster/nextid)
pct create $CTID local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst \
--hostname lan-client \
--memory 256 \
--rootfs local-lvm:2 \
--net0 name=eth0,bridge=vmbr1,ip=dhcp \
--password test1234 \
--unprivileged 1 \
--start 1
sleep 15
pct exec $CTID -- ip addr show eth0
Результат:
2: eth0@if166: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
link/ether bc:24:11:c5:3c:5a brd ff:ff:ff:ff:ff:ff
inet 192.168.88.254/24 metric 1024 brd 192.168.88.255 scope global dynamic eth0
valid_lft 1786sec preferred_lft 1786sec
Клиент получил 192.168.88.254 из пула CHR. Адрес динамический — флаг dynamic.
Шаг 12. Проверяем DHCP lease на CHR
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/ip dhcp-server lease print"
Результат:
Flags: D - DYNAMIC
Columns: ADDRESS, MAC-ADDRESS, HOST-NAME, SERVER, STATUS, LAST-SEEN
# ADDRESS MAC-ADDRESS HOST-NAME SERVER STATUS LAST-SEEN
0 D 192.168.88.254 BC:24:11:C5:3C:5A lan-client lan-dhcp bound 22s
CHR видит клиента — MAC адрес, hostname, статус bound. Lease активен.
Шаг 13. Проверяем интернет с клиента
Пингуем сначала IP — проверяем SNAT. Потом домен — проверяем DNS:
pct exec 111 -- ping -c 3 8.8.8.8
pct exec 111 -- ping -c 3 google.com
Результат:
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=103 time=37.3 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=103 time=36.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=103 time=38.1 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, packet-loss=0%
PING google.com (74.125.131.102) 56(84) bytes of data.
64 bytes from lu-in-f102.1e100.net: icmp_seq=1 ttl=103 time=36.4 ms
64 bytes from lu-in-f102.1e100.net: icmp_seq=2 ttl=103 time=37.4 ms
64 bytes from lu-in-f102.1e100.net: icmp_seq=3 ttl=103 time=37.5 ms
--- google.com ping statistics ---
3 packets transmitted, 3 received, packet-loss=0%
SNAT работает — пакеты идут наружу. DNS резолвится — CHR отвечает на запросы клиентов. Потери нулевые.
Шаг 14. Финальный бэкап
ssh -o StrictHostKeyChecking=no -p 2222 -i /root/.ssh/mikrotik_key sys0dmin@192.168.168.29 \
"/system backup save name=chr-nat-dhcp"
Таблица портов и интерфейсов
| Интерфейс |
IP |
Сеть |
Назначение |
| ether1 |
192.168.168.29/24 |
192.168.168.0/24 |
WAN — выход в интернет |
| ether2 |
192.168.88.1/24 |
192.168.88.0/24 |
LAN — шлюз для клиентов |
| Параметр |
Значение |
| DHCP пул |
192.168.88.10 — 192.168.88.254 |
| Шлюз для клиентов |
192.168.88.1 |
| DNS для клиентов |
8.8.8.8, 8.8.4.4 |
| SNAT to-address |
192.168.168.29 |
| Дефолтный шлюз CHR |
192.168.168.1 |
Troubleshooting
После удаления DHCP клиента SSH отвалился
Подключайся через консоль Proxmox и назначай статику вручную:
qm terminal 110
В консоли CHR:
/ip address add address=192.168.168.29/24 interface=ether1
/ip route add dst-address=0.0.0.0/0 gateway=192.168.168.1
LXC контейнер не получает IP по DHCP
Проверь что DHCP сервер запущен на правильном интерфейсе:
/ip dhcp-server print
/ip dhcp-server network print
Проверь что ether2 имеет IP:
/ip address print
Если ether2 без адреса — DHCP сервер не знает из какой подсети выдавать адреса.
Клиент получил IP но интернета нет
Проверяем по шагам. Сначала пинг шлюза:
pct exec 111 -- ping -c 3 192.168.88.1
Если не пингуется — проблема в bridge или интерфейсе ether2. Если пингуется — проверяем SNAT:
/ip firewall nat print
Проверяем правила forward:
/ip firewall filter print where chain=forward
Появился ether3 вместо ether2
RouterOS запомнил MAC от предыдущего интерфейса. Переименовываем:
/interface set ether3 name=ether2
Как проверить что SNAT работает
Смотрим счётчики пакетов на правиле — они должны расти при активном трафике:
/ip firewall nat print stats where comment=snat-lan
FAQ
Чем SNAT отличается от masquerade?
Masquerade — это частный случай SNAT где исходящий IP определяется автоматически по интерфейсу. Удобно когда IP меняется — например при динамическом WAN. SNAT требует указать конкретный адрес явно, зато работает быстрее — не нужно вычислять IP на каждый пакет. При статическом WAN IP всегда используй SNAT.
Почему пул начинается с .10 а не с .2?
Адреса .1-.9 оставляем для статических назначений — принтеры, камеры, серверы которым нужен постоянный IP. Так не придётся делать статические резервации в DHCP для каждого такого устройства.
Как назначить конкретный IP определённому клиенту?
Через статическую привязку по MAC в DHCP:
/ip dhcp-server lease add address=192.168.88.50 mac-address=BC:24:11:C5:3C:5A server=lan-dhcp
Как посмотреть кто сейчас в сети?
/ip dhcp-server lease print where status=bound
Как удалить vmbr1 если он больше не нужен?
ifdown vmbr1
sed -i '/^auto vmbr1/,/^$/d' /etc/network/interfaces
Что дальше
Стенд теперь полноценный — CHR маршрутизирует трафик между двумя сетями, раздаёт адреса по DHCP и транслирует их через SNAT при выходе в интернет. Это базовая схема которая используется в большинстве реальных установок.
Следующая статья цикла — настройка VPN на MikroTik CHR. Поднимем WireGuard туннель для безопасного удалённого доступа в LAN сеть.
Не заработало - разберёмся
Пиши в комментарии. Описывай: версию
CHR и Proxmox, что именно делал, какую ошибку получил. Разберём.