Skip to content

WireGuard — mihomo ​

Исходящий WireGuard в mihomo работает в пользовательском пространстве на выбираемом IP-стеке (gVisor или собственный стек mips в mihomo — см. ip-stack). Схема предлагает и упрощённую однопировую форму (поля пира лежат в корне прокси), и развёрнутую многопировую через peers:. Необязательный блок amnezia-wg-option обеспечивает совместимость с серверами семейства AmneziaWG.

Исходящий ​

Запись в proxies: с type: wireguard. Встраивает BasicOption, а также упрощённые поля пира из WireGuardPeerOption.

ПолеТипПо умолчаниюДопустимые значенияОписание
namestring(required)<string>Уникальное имя прокси.
ipstring(unset)<IPv4 CIDR>Локальный IPv4-адрес туннеля (например, 10.0.0.2/32).
ipv6string(unset)<IPv6 CIDR>Локальный IPv6-адрес туннеля.
private-keystring(required)<base64 key>Локальный закрытый ключ.
workersint(CPU-based)<int>Число воркеров конвейера шифрования.
mtuint1408<bytes>MTU туннеля.
udpboolfalsetrue | falseВключить ретрансляцию UDP.
persistent-keepaliveint0<seconds>Интервал persistent-keepalive. 0 отключает keepalive.
ip-stackIPStackOption(auto)IPStackOptionIP-стек в пользовательском пространстве, который несёт TCP/UDP-трафик туннеля. См. таблицу ip-stack ниже.
amnezia-wg-option*AmneziaWGOption(unset)AmneziaWGOptionПараметры обфускации AmneziaWG (мусорные пакеты, маскировка заголовков).
peers[]WireGuardPeerOption(use simplified shape)[WireGuardPeerOption]Развёрнутый список нескольких пиров. Когда задан, встроенные упрощённые поля игнорируются.
remote-dns-resolveboolfalsetrue | falseРазрешать DNS-запросы через туннель WireGuard, используя резолверы на стороне пира.
dns[]string[][<DNS server>]Резолверы, используемые внутри туннеля, когда remote-dns-resolve равен true.
refresh-server-ip-intervalint0<seconds>Повторно разрешать имена хостов пиров каждые N секунд. 0 отключает периодическое повторное разрешение.

Исходный код: adapter/outbound/wireguard.go:69-91 · зафиксировано на v1.19.31 (ab405ba)

peers[] — многопировая форма ​

ПолеТипПо умолчаниюДопустимые значенияОписание
serverstring(required)<host>Имя хоста или IP пира.
portint(required)<port>UDP-порт пира.
public-keystring(required)<base64 key>Открытый ключ пира.
pre-shared-keystring(unset)<base64 key>Необязательный PSK.
reserved[]uint8(empty)<3 bytes>Переопределение 3-байтового поля reserved.
allowed-ips[]string[][<CIDR>]Allowed-IPs для этого пира.

Исходный код: adapter/outbound/wireguard.go:93-100 · зафиксировано на v1.19.31 (ab405ba)

ip-stack ​

ПолеТипПо умолчаниюДопустимые значенияОписание
modestringautoauto | gvisor | mipsgvisor — сетевой стек gVisor (только в сборках с тегом with_gvisor, иначе запуск завершится ошибкой); mips — собственный IP-стек mihomo (MIPS — это mihomo IP stack, а не архитектура процессора); auto выбирает gVisor, если он вкомпилирован, иначе mips.
congestion-controllerstring(stack default)cubic | reno | bbr | bbr3Алгоритм управления перегрузкой TCP для стека mips. gVisor его игнорирует. Любое другое значение отклоняется при запуске.

Исходный код: adapter/outbound/wireguard.go:143-146 · зафиксировано на v1.19.31 (ab405ba)

amnezia-wg-option ​

ПолеТипПо умолчаниюДопустимые значенияОписание
versionint03 | <other>Выбор реализации. 3 переключает на реализацию AmneziaWG v3, которая нужна полям только-v3 ниже; любое другое значение (в том числе незаданное) использует прежнюю реализацию v1.x/v2.
jcint0<int>Число мусорных пакетов на рукопожатие.
jminint0<bytes>Минимальный размер мусорного пакета.
jmaxint0<bytes>Максимальный размер мусорного пакета.
s1int0<bytes>Длина дополнения перед init-пакетом.
s2int0<bytes>Длина дополнения перед response-пакетом.
s3int0<bytes>AmneziaWG v1.5+ — длина дополнения перед cookie-пакетом.
s4int0<bytes>AmneziaWG v1.5+ — длина дополнения перед data-пакетом.
h1string(unset)<uint32> | <min-max>Магическое значение заголовка init-пакета. Только десятичное — в v1.x одно значение uint32; v2+ также принимает диапазон min-max.
h2string(unset)<uint32> | <min-max>Магическое значение заголовка response-пакета. Формат как у h1.
h3string(unset)<uint32> | <min-max>Магическое значение заголовка cookie-пакета. Формат как у h1.
h4string(unset)<uint32> | <min-max>Магическое значение заголовка data-пакета. Формат как у h1.
i1string(unset)<tag chain>AmneziaWG v1.5+ — специальный пакет 1, записывается цепочкой тегов, например <b 0xf6ab3267fa><r 100>.
i2string(unset)<tag chain>Специальный пакет 2 (формат как у i1).
i3string(unset)<tag chain>Специальный пакет 3 (формат как у i1).
i4string(unset)<tag chain>Специальный пакет 4 (формат как у i1).
i5string(unset)<tag chain>Специальный пакет 5 (формат как у i1).
j1string(unset)<tag chain>Только AmneziaWG v1.5 — мусорный пакет 1 (цепочка тегов). Отклоняется при version: 3.
j2string(unset)<tag chain>Только AmneziaWG v1.5 — мусорный пакет 2 (цепочка тегов). Отклоняется при version: 3.
j3string(unset)<tag chain>Только AmneziaWG v1.5 — мусорный пакет 3 (цепочка тегов). Отклоняется при version: 3.
itimeint640<seconds>Только AmneziaWG v1.5 — периодичность отправки мусорных пакетов. Отклоняется при version: 3.
header-protection-keystring(unset)<base64 key>AmneziaWG v3 — ключ (base64, например из awg genkey) для шифрования низкоэнтропийных полей заголовка. Требует, чтобы s1–s4 были не меньше 12.
content-padding-additionstring(unset)<bytes> | <a-b>AmneziaWG v3 — диапазон дополнительного случайного дополнения содержимого пакета, в байтах (a или a-b). Лучше задавать одинаково на обеих сторонах.
rekey-after-timestring(unset)<seconds> | <a-b>AmneziaWG v3 — через сколько секунд клиент начинает новое рукопожатие (a или a-b).
rekey-timeoutstring(unset)<seconds> | <a-b>AmneziaWG v3 — сколько секунд ждать, прежде чем повторить рукопожатие без ответа.
reject-after-timestring(unset)<seconds> | <a-b>AmneziaWG v3 — через сколько секунд клиент принудительно выполняет рукопожатие и отклоняет входящие данные старой сессии.
keepalive-timeoutstring(unset)<seconds> | <a-b>AmneziaWG v3 — через сколько секунд после последней отправки данных посылается keepalive.
max-handshake-attemptsstring(unset)<int> | <a-b>AmneziaWG v3 — максимальное число повторов рукопожатия.
random-trailersboolfalsetrue | falseAmneziaWG v3.1 — добавлять к пакетам хвосты случайной длины (и принимать от пира пакеты длиннее ожидаемого).
disable-cookiesboolfalsetrue | falseAmneziaWG v3.1 — не отвечать cookie-пакетами даже под нагрузкой (пропускает проверку MAC2 WireGuard против DoS).

Исходный код: adapter/outbound/wireguard.go:102-141 · зафиксировано на v1.19.31 (ab405ba)

Примеры ​

Упрощённое однопировое исходящее:

yaml
proxies:
  - name: wg-simple
    type: wireguard
    server: wg.example.com
    port: 51820
    private-key: <base64>
    public-key: <base64 peer key>
    ip: 10.0.0.2/32
    ipv6: fd00::2/128
    allowed-ips: ['0.0.0.0/0', '::/0']
    udp: true
    persistent-keepalive: 25

Многопировое исходящее (например, топология «хаб и спицы»):

yaml
proxies:
  - name: wg-multi
    type: wireguard
    private-key: <base64>
    ip: 10.0.0.2/32
    udp: true
    peers:
      - server: spoke1.example.com
        port: 51820
        public-key: <base64-spoke1>
        allowed-ips: ['10.0.1.0/24']
      - server: spoke2.example.com
        port: 51820
        public-key: <base64-spoke2>
        allowed-ips: ['10.0.2.0/24']

Исходящее, совместимое с AmneziaWG:

yaml
proxies:
  - name: awg
    type: wireguard
    server: awg.example.com
    port: 12345
    private-key: <base64>
    public-key: <base64>
    ip: 10.13.13.2/32
    allowed-ips: ['0.0.0.0/0']
    udp: true
    amnezia-wg-option:
      jc: 4
      jmin: 40
      jmax: 80
      s1: 0
      s2: 0
      h1: 123456
      h2: 67543
      h3: 123123
      h4: 32345

Исходящее AmneziaWG v3:

yaml
proxies:
  - name: awg3
    type: wireguard
    server: awg.example.com
    port: 12345
    private-key: <base64>
    public-key: <base64>
    ip: 10.13.13.2/32
    allowed-ips: ['0.0.0.0/0']
    udp: true
    amnezia-wg-option:
      version: 3
      jc: 4
      jmin: 40
      jmax: 80
      s1: 16
      s2: 16
      s3: 16
      s4: 16
      h1: 100000-199999
      h2: 200000-299999
      h3: 300000-399999
      h4: 400000-499999
      header-protection-key: <base64 key>
      content-padding-addition: 0-32

Примечания ​

  • mihomo принимает и упрощённую форму (server/port/public-key/allowed-ips на верхнем уровне), и развёрнутый список peers:. Когда задан peers, встроенные упрощённые поля игнорируются.
  • remote-dns-resolve: true заставляет WireGuard туннелировать DNS-запросы к резолверам из dns: (вместо использования локального резолвера). Полезно, когда локальный DNS не достигает назначения.
  • refresh-server-ip-interval имеет значение, только когда server пира — имя хоста; поле повторно разрешает его с фиксированным интервалом, что полезно для конечных точек с динамическим DNS.
  • Поля amnezia-wg-option версионированы: s3/s4/i1-i5 — AmneziaWG v1.5+; j1/j2/j3/itime — только v1.5 (в v2 и выше не используются); header-protection-key, content-padding-addition и пять полей таймингов — только v3, а random-trailers / disable-cookies требуют v3.1. Поля v3 требуют version: 3 и не сочетаются с полями только-v1.5 — каждая реализация отклоняет параметры другой. См. комментарии в исходниках: adapter/outbound/wireguard.go:103-140.
  • ip-stack.mode: auto выбирает gVisor в сборках, где он есть, и собственный стек mips mihomo в остальных; congestion-controller действует только на mips. Тот же блок ip-stack есть у исходящих OpenVPN и MASQUE в mihomo.

Сравнение с другими ядрами ​

  • Xray-core всегда использует peers: (без упрощённой формы), предоставляет флаг noKernelTun для быстрого пути в Linux и именует поля в camelCase (secretKey, address, publicKey). См. WireGuard — Xray-core.
  • sing-box настраивает WireGuard как конечную точку в endpoints[], а не в outbounds[]. Имена полей в snake_case (private_key, allowed_ips). См. WireGuard — sing-box.

Исходный код: adapter/outbound/wireguard.go:69-141 · v1.19.31 (ab405ba)

Core Tutorial от Argsment