Содержание

Домашний роутер (OpenWrt)

192.168.0.1 — главная точка периметра. Делает всё: маршрутизация, NAT, DHCP, DNS-фильтрация, Wi-Fi, reverse-proxy, TLS, VPN-сервер, ZeroTier-gateway, мониторинг трафика, watchdog'и для критичных сервисов.

Что это за железо

Архитектура трафика

                 ┌─────────────────────────────┐
                 │   ИНТЕРНЕТ (Cloudflare DNS) │
                 └─────────────┬───────────────┘
                               │
                  WAN  eth1    │ public 95.165.74.182/19
                  metric 1     │
       LTE  mbim  metric 20    │
        (резерв) │             │
                 │             │
        ┌────────▼─────────────▼────────┐
        │  GL-MT6000 (192.168.0.1)      │
        │                               │
        │  nginx :80/:443  ←── *.melnoff.com (TLS, ACME)
        │  ZeroTier :9993  ←── ZT-leaf 31040019d0  ⇄ moon
        │  AmneziaWG :51820 ←── обфусц. VPN сервер
        │  AdGuardHome :53  ←── DNS для LAN
        │  dnsmasq :5353    ←── DHCP + .lan имена
        │  uhttpd 127.0.0.1:8082 ←── LuCI веб-админка
        └──┬──────┬──────┬─────────────┬┘
   br-lan.1│      │br-lan.2            │zt7t5aodqt (172.25.30.1/24)
  VLAN 1   │      │VLAN 2              │
  192.168.0/24    │172.16.10/24        │ ZeroTier overlay
   ┌──────▼─┐   ┌─▼──────────┐   ┌────▼────────────────┐
   │ LAN+   │   │ Docker     │   │ Внешние ZT-клиенты  │
   │ Wi-Fi  │   │ fabric     │   │ (мак, телефон,      │
   │        │   │ (PVE VMs   │   │  удалённый peer .6) │
   │ HomePC │   │  + LXC 107)│   └─────────────────────┘
   │ NAS    │   │ docker-lxc │
   │ ...    │   │ vm-2/3/5   │
   └────────┘   └────────────┘

WAN: основной канал + LTE-резерв

Основной WAN

LTE-резерв

Failover (mwan3)

mwan3 переключает default-маршрут между WAN и LTE по результатам ping-проб 8.8.8.8 и 1.1.1.1 раз в 5 секунд:

LAN и VLAN

Бриджи и интерфейсы

Логический интерфейс Device IP/маска Состав
lan br-lan.1 (VLAN 1) 192.168.0.1/24 физ. порты lan1-lan4 + phy0-ap0 (2.4 GHz) + phy1-ap0 (5 GHz)
vlan2_vms br-lan.2 (VLAN 2) 172.16.10.254/24 только lan2:t (tagged)
management br-mgmt 192.168.1.1/24 физ. порт lan5 (сейчас DOWN)
zerotier zt7t5aodqt (none, IP даёт ZT) оверлей, IP 172.25.30.1
awg0 awg0 10.10.10.1/24 AmneziaWG-сервер

Принцип

Wi-Fi

SSID Band HT mode Encryption Country
MELNOFF_2GHz 2.4 GHz HE40 (Wi-Fi 6) WPA2-PSK RU
MELNOFF_5GHz 5 GHz HE80 (Wi-Fi 6) WPA2-PSK RU

Оба radio привязаны к сети lan (VLAN 1), channel auto.

ZeroTier на самом роутере

⭐ Роутер сам является участником ZT-сети melnoff-main-network и одновременно работает gateway-узлом.

ZT-watchdog

/etc/scripts/zt-watchdog.sh — каждые 5 минут (cron):

#!/bin/sh
# ZeroTier peer watchdog
PEERS="172.25.30.3 172.25.30.6 172.25.30.10"
FAIL=0
TOTAL=0
for ip in $PEERS; do
    TOTAL=$((TOTAL+1))
    ping -c1 -W3 $ip >/dev/null 2>&1 || FAIL=$((FAIL+1))
done
if [ $FAIL -gt 1 ]; then
    logger -t zt-watchdog "$FAIL/$TOTAL peers unreachable, restarting zerotier"
    service zerotier restart
fi

Защищает от залипания ZT-демона: если 2 из 3 контрольных пиров не пингуются — перезапуск.

AmneziaWG (VPN-сервер)

AmneziaWG = форк WireGuard с обфускацией заголовков для обхода DPI. У вас он работает как сервер для клиентов «снаружи» (телефон в роуминге и т.п.).

Reverse-proxy и TLS

Подробный рецепт публикации сервиса под <name>.melnoff.com — см. тут.

DNS: AdGuardHome + dnsmasq

Двухуровневая схема:

client → 192.168.0.1:53  (AdGuardHome)
                  │
                  ├── upstream → 1.1.1.1, 8.8.8.8
                  │
                  ├── rewrites (homepc.zt и т.п.) → 192.168.0.11 / 172.16.10.1
                  │
                  └── forward → 127.0.0.1:5353  (dnsmasq, локальные .lan имена + DHCP)

DHCP + статические резервации

Резервации (статические IP по MAC)

IP Имя Что (предположительно)
192.168.0.5 host-5 Synology NAS
192.168.0.6 host-6 PVE (Proxmox)
192.168.0.8 host-8
192.168.0.9 host-9
192.168.0.10 host-10
192.168.0.11 HomePC хост, на котором живёт homepc.zt DNS-зона
192.168.0.18,20,22..24,30..32 host-N разные клиенты
192.168.0.100,131..134,201 host-N ещё клиенты
172.16.10.1 docker-lxc LXC 107 на PVE — главный Docker-host
172.16.10.2 vm-2 VM на PVE
172.16.10.3 vm-3 VM на PVE
172.16.10.4 claude-router (?)
172.16.10.5 vm-5 VM на PVE

Firewall

Default policy

input=REJECT, output=ACCEPT, forward=REJECT, syn_flood=on — sane defaults.

Зоны

Зона Input Output Forward Состав
lan ACCEPT ACCEPT ACCEPT lan, vlan2_vms, management, zerotier (zt7t5aodqt)
wan REJECT ACCEPT DROP (masq, mtu_fix) wan, lte
awg ACCEPT ACCEPT ACCEPT awg0

Forwarding

Открытые порты на WAN

Port Proto Куда Что
80 tcp local nginx HTTP redirect to HTTPS + ACME challenge
443 tcp local nginx HTTPS (*.melnoff.com vhosts)
9993 udp local ZeroTier-демон
51820 udp local AmneziaWG
2244 tcp DNAT → 172.16.10.1:2244 Gitea SSH
1804 tcp DNAT → 192.168.0.11:1804 RDP на HomePC (нестандартный порт)
ICMP echo reachability
IGMP, DHCP renew системные

SSH (22) и LuCI (uhttpd/nginx)не открыты на WAN, только из LAN/AWG/ZT.

Service watchdog

/etc/scripts/service-watchdog.sh (раз в минуту через cron) автоматически рестартует упавшие сервисы и проверяет AdGuard функционально:

#!/bin/sh
restart_if_dead() {
    local name="$1" proc="$2"
    if ! pidof "$proc" > /dev/null; then
        logger -t watchdog "$name is down, restarting..."
        service "$name" restart
        sleep 3
        if ! pidof "$proc" > /dev/null; then
            logger -t watchdog "$name still down after service restart, trying direct start"
            case "$proc" in
                AdGuardHome)
                    start-stop-daemon -S -b -x /usr/bin/AdGuardHome -- \
                        --config /etc/adguardhome/adguardhome.yaml \
                        --logfile syslog --no-check-update \
                        --work-dir /etc/adguardhome
                    ;;
            esac
        fi
    fi
}
 
restart_if_dead xray xray
restart_if_dead byedpi ciadpi
restart_if_dead adguardhome AdGuardHome
restart_if_dead zerotier zerotier-one
 
# AdGuard functional check
if pidof AdGuardHome > /dev/null; then
    result=$(nslookup ya.ru 192.168.0.1 2>&1)
    if echo "$result" | grep -q 'SERVFAIL\|REFUSED\|timed out\|connection refused'; then
        logger -t watchdog "AdGuard DNS not resolving, force restarting..."
        kill -9 $(pidof AdGuardHome) 2>/dev/null
        sleep 2
        start-stop-daemon -S -b -x /usr/bin/AdGuardHome -- ...
    fi
fi

Под мониторингом: xray, byedpi/ciadpi (anti-DPI инструменты), AdGuardHome, zerotier-one. Помимо pidof — функциональная DNS-проверка для AdGuard: если упирается в SERVFAIL/REFUSED — kill -9 и пересоздание процесса.

Прочие сервисы

Cron-таски

0 0  * * *   /etc/init.d/acme renew              # ежедневное обновление сертификатов
3 3 12 12 *  /usr/bin/nginx-util check_ssl       # годовая проверка SSL
* *  * * *   /etc/scripts/service-watchdog.sh    # каждую минуту
*/5 * * * *  /etc/scripts/zt-watchdog.sh         # каждые 5 минут

Конфиги (UCI exports, секреты замаскированы)

/etc/config/network

network
config interface 'loopback'
    option device 'lo'
    option proto 'static'
    option ipaddr '127.0.0.1'
    option netmask '255.0.0.0'
 
config globals 'globals'
    option packet_steering '1'
 
# === BRIDGES ===
config device
    option name 'br-lan'
    option type 'bridge'
    list ports 'lan1'
    list ports 'lan2'
    list ports 'lan3'
    list ports 'lan4'
 
config device
    option type 'bridge'
    option name 'br-mgmt'
    list ports 'lan5'
 
# === BRIDGE VLANs ===
config bridge-vlan
    option device 'br-lan'
    option vlan '1'
    list ports 'lan1'
    list ports 'lan2'
    list ports 'lan3'
    list ports 'lan4'
    list ports 'phy0-ap0'
    list ports 'phy1-ap0'
 
config bridge-vlan
    option device 'br-lan'
    option vlan '2'
    list ports 'lan2:t'
 
# === L3 INTERFACES ===
config interface 'lan'
    option device 'br-lan.1'
    option proto 'static'
    option ipaddr '192.168.0.1'
    option netmask '255.255.255.0'
 
config interface 'vlan2_vms'
    option proto 'static'
    option ipaddr '172.16.10.254'
    option netmask '255.255.255.0'
    option device 'br-lan.2'
 
config interface 'management'
    option proto 'static'
    option device 'br-mgmt'
    option ipaddr '192.168.1.1'
    option netmask '255.255.255.0'
 
config interface 'wan'
    option device 'eth1'
    option proto 'dhcp'
 
config interface 'lte'
    option proto 'mbim'
    option device '/dev/cdc-wdm0'
    option apn 'internet.mts.ru'
    option metric '20'
 
config interface 'zerotier'
    option proto 'none'
    option device 'zt7t5aodqt'
 
# === AMNEZIAWG SERVER ===
config interface 'awg0'
    option proto 'amneziawg'
    option private_key '***REDACTED***'
    option listen_port '51820'
    list addresses '10.10.10.1/24'
    option awg_jc '4'
    option awg_jmin '40'
    option awg_jmax '70'
    option awg_s1 '0'
    option awg_s2 '0'
    option awg_h1 '1'
    option awg_h2 '2'
    option awg_h3 '3'
    option awg_h4 '4'
    option mtu '1280'
 
config amneziawg_awg0
    option description 'Phone'
    option public_key '1c1KX8pjJ70aNFRha3w6+I5g9n4dZnJSMoiz3gJ0BV8='
    option preshared_key '***REDACTED***'
    list allowed_ips '10.10.10.2/32'
    option persistent_keepalive '25'

/etc/config/wireless

wireless
config wifi-device 'radio0'
    option type 'mac80211'
    option path 'platform/soc/18000000.wifi'
    option band '2g'
    option channel 'auto'
    option htmode 'HE40'
    option country 'RU'
 
config wifi-iface 'default_radio0'
    option device 'radio0'
    option network 'lan'
    option mode 'ap'
    option ssid 'MELNOFF_2GHz'
    option encryption 'psk2'
    option key '***REDACTED***'
 
config wifi-device 'radio1'
    option type 'mac80211'
    option path 'platform/soc/18000000.wifi+1'
    option band '5g'
    option channel 'auto'
    option htmode 'HE80'
    option country 'RU'
 
config wifi-iface 'default_radio1'
    option device 'radio1'
    option network 'lan'
    option mode 'ap'
    option ssid 'MELNOFF_5GHz'
    option encryption 'psk2'
    option key '***REDACTED***'

/etc/config/dhcp (без полного списка резерваций)

dhcp
config dnsmasq
    option domainneeded '1'
    option boguspriv '1'
    option rebind_protection '1'
    option local '/lan/'
    option domain 'lan'
    option expandhosts '1'
    option cachesize '1000'
    option authoritative '1'
    option leasefile '/tmp/dhcp.leases'
    option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
    option localservice '1'
    option filter_aaaa '1'
    option port '5353'   # AdGuardHome занимает 53
    option logdhcp '1'
 
config dhcp 'lan'
    option interface 'lan'
    option start '10'
    option limit '91'
    option leasetime '12h'
    option dhcpv4 'server'
    list dhcp_option '6,192.168.0.1'
 
config dhcp 'wan'
    option interface 'wan'
    option ignore '1'
 
config dhcp 'management'
    option interface 'management'
    option start '2'
    option limit '9'
    option leasetime '30m'
    list dhcp_option '3,192.168.1.1'
    list dhcp_option '6,192.168.0.1'
 
config dhcp 'vlan2_vms'
    option interface 'vlan2_vms'
    option start '100'
    option limit '154'
    option leasetime '12h'
    list dhcp_option '3,172.16.10.254'
    list dhcp_option '6,192.168.0.1'
    option dhcpv4 'server'
 
# Static reservations (~25 хостов) опущены — см. таблицу выше.

/etc/config/firewall

firewall
config defaults
    option syn_flood '1'
    option input 'REJECT'
    option output 'ACCEPT'
    option forward 'REJECT'
 
config zone
    option name 'lan'
    option input 'ACCEPT'
    option output 'ACCEPT'
    option forward 'ACCEPT'
    list network 'lan'
    list network 'vlan2_vms'
    list network 'management'
    list network 'zerotier'
    list device 'zt7t5aodqt'
 
config zone
    option name 'wan'
    list network 'wan'
    list network 'lte'
    option input 'REJECT'
    option output 'ACCEPT'
    option forward 'DROP'
    option masq '1'
    option mtu_fix '1'
 
config zone
    option name 'awg'
    option input 'ACCEPT'
    option output 'ACCEPT'
    option forward 'ACCEPT'
    option masq '0'
    list network 'awg0'
 
config forwarding
    option src 'lan'
    option dest 'wan'
 
config forwarding
    option src 'awg'
    option dest 'lan'
 
config forwarding
    option src 'awg'
    option dest 'wan'
 
config forwarding
    option src 'lan'
    option dest 'awg'
 
# === WAN INPUT RULES ===
config rule
    option name 'Allow-DHCP-Renew'
    option src 'wan'
    option proto 'udp'
    option dest_port '68'
    option family 'ipv4'
    option target 'ACCEPT'
 
config rule
    option name 'Allow-Ping'
    option src 'wan'
    option proto 'icmp'
    option icmp_type 'echo-request'
    option family 'ipv4'
    option target 'ACCEPT'
 
config rule
    option name 'Allow-IGMP'
    option src 'wan'
    option proto 'igmp'
    option family 'ipv4'
    option target 'ACCEPT'
 
config rule
    option name 'Allow-ZeroTier-WAN'
    option src 'wan'
    option proto 'udp'
    option dest_port '9993'
    option target 'ACCEPT'
 
config rule
    option name 'Allow-HTTP-In'
    option src 'wan'
    option proto 'tcp'
    option dest_port '80'
    option target 'ACCEPT'
 
config rule
    option name 'Allow-HTTPS-In'
    option src 'wan'
    option proto 'tcp'
    option dest_port '443'
    option target 'ACCEPT'
 
config rule
    option name 'Allow-AWG'
    option src 'wan'
    option proto 'udp'
    option dest_port '51820'
    option target 'ACCEPT'
 
# === DNAT REDIRECTS ===
config redirect
    option name 'Proxy-2244'    # gitea SSH
    option src 'wan'
    option dest 'lan'
    option proto 'tcp'
    option src_dport '2244'
    option dest_ip '172.16.10.1'
    option target 'DNAT'
 
config redirect
    option name 'HomePC RDP'
    option src 'wan'
    option dest 'lan'
    option target 'DNAT'
    option proto 'tcp'
    option src_dport '1804'
    option dest_ip '192.168.0.11'

/etc/config/system

system
config system
    option hostname 'gl-mt6000'
    option timezone 'MSK-3'
    option zonename 'Europe/Moscow'
    option ttylogin '0'
    option log_size '128'
 
config timeserver 'ntp'
    list server 'ntp1.stratum2.ru'
    list server '0.openwrt.pool.ntp.org'
    list server '1.openwrt.pool.ntp.org'

/etc/config/dropbear

dropbear
config dropbear 'main'
    option enable '1'
    option PasswordAuth 'on'
    option RootPasswordAuth 'on'
    option Port '22'

/etc/config/mwan3

mwan3
config globals 'globals'
    option mmx_mask '0x3F00'
    option local_source 'lan'
 
config interface 'wan'
    option enabled '1'
    option family 'ipv4'
    option count '1'
    option timeout '2'
    option interval '5'
    option down '3'
    option up '8'
    list track_ip '8.8.8.8'
    list track_ip '1.1.1.1'
 
config interface 'lte'
    option enabled '1'
    option family 'ipv4'
    option count '1'
    option timeout '2'
    option interval '5'
    option down '3'
    option up '8'
    list track_ip '8.8.8.8'
    list track_ip '1.1.1.1'
 
config member 'wan_m1'
    option interface 'wan'
    option metric '1'
    option weight '1'
 
config member 'lte_m2'
    option interface 'lte'
    option metric '2'
    option weight '1'
 
config policy 'failover'
    list use_member 'wan_m1'
    list use_member 'lte_m2'
 
config rule 'default_rule'
    option dest_ip '0.0.0.0/0'
    option sticky '0'
    option use_policy 'failover'

/etc/config/zerotier

zerotier
config zerotier 'global'
    option enabled '1'
    option config_path '/etc/zerotier'
    option secret '***REDACTED***'
 
config network 'melnoff'
    option id 'c53bc939c1ce37d2'
    option allow_managed '1'
    option allow_global '0'
    option allow_default '0'
    option allow_dns '0'

/etc/config/upnpd

upnpd
config upnpd 'config'
    option enabled '1'
    option enable_natpmp '1'
    option enable_upnp '1'
    option secure_mode '1'
    option download '1024'
    option upload '512'
    option internal_iface 'lan'
    option external_iface 'wan'
    option port '5000'
    option uuid '***REDACTED***'
 
config perm_rule
    option action 'allow'
    option ext_ports '1024-65535'
    option int_addr '0.0.0.0/0'
    option int_ports '1024-65535'
 
config perm_rule
    option action 'deny'
    option ext_ports '0-65535'
    option int_addr '0.0.0.0/0'
    option int_ports '0-65535'

/etc/config/nlbwmon

nlbwmon
config nlbwmon
    option netlink_buffer_size '524288'
    option commit_interval '24h'
    option refresh_interval '30s'
    option database_directory '/var/lib/nlbwmon'
    option database_generations '10'
    option database_interval '1'
    option database_limit '10000'
    option protocol_database '/usr/share/nlbwmon/protocols'
    list local_network '192.168.0.0/16'
    list local_network '172.16.0.0/12'
    list local_network '10.0.0.0/8'
    list local_network 'lan'

/etc/config/acme (только активные сертификаты)

acme
config acme
    option account_email 'admin@melnoff.com'
    option debug '1'
 
# Все active cert'ы — webroot http-01, ec256 ключ
config cert 'nas'
    option enabled '1'
    option validation_method 'webroot'
    option key_type 'ec256'
    list domains 'nas.melnoff.com'
 
config cert 'git'
    option enabled '1'
    option validation_method 'webroot'
    option key_type 'ec256'
    option domains 'git.melnoff.com'
 
config cert 'bw'
    option enabled '1'
    option validation_method 'webroot'
    option key_type 'ec256'
    option domains 'bw.melnoff.com'
 
config cert 'luci'
    option enabled '1'
    option validation_method 'webroot'
    option webroot '/var/run/acme/challenge'
    option key_type 'ec256'
    option domains 'luci.melnoff.com'
 
config cert
    option enabled '1'
    option validation_method 'webroot'
    option webroot '/var/run/acme/challenge'
    option key_type 'ec256'
    list domains 'admin.corginet.ru'
 
config cert 'argo'
    option enabled '1'
    option validation_method 'webroot'
    option webroot '/var/run/acme/challenge'
    option key_type 'ec256'
    list domains 'argo.melnoff.com'
    list domains 'chat.argo.melnoff.com'
    list domains 'n8n.argo.melnoff.com'
 
config cert 'litellm'
    option enabled '1'
    option validation_method 'webroot'
    option webroot '/var/run/acme/challenge'
    option key_type 'ec256'
    option domains 'litellm.melnoff.com'
 
config cert 'fooocus'
    option enabled '1'
    option validation_method 'webroot'
    option webroot '/var/run/acme/challenge'
    option key_type 'ec256'
    option domains 'fooocus.melnoff.com'
 
config cert 'wiki'
    option enabled '1'
    option validation_method 'webroot'
    option key_type 'ec256'
    option domains 'wiki.melnoff.com'

Замечания и идеи на улучшение

Безопасность

  1. dropbear.RootPasswordAuth = on + PasswordAuth = on — root по паролю включён на SSH. На WAN-зоне порт 22 закрыт (атакующий должен сначала попасть в LAN/AWG/ZT), но это всё равно лишний риск. Лучше отключить и оставить только key-based.
  2. UPnP включён в secure_mode с правом открывать 1024–65535. Любая программа в LAN (включая случайно установленную) может пробить себе порт наружу. Если активно не используется — отключить.
  3. RDP проброшен наружу (wan:1804 → 192.168.0.11:1804). RDP — постоянная цель брутфорса, даже на нестандартном порту. Стоит спрятать его за AWG/ZT и убрать redirect.

Чего не хватает / что стоит добавить

Известные мелочи