Шукати в цьому блозі

вівторок, 26 серпня 2025 р.

CloudFlare Client на MikroTIK (RouterOS)

Перше, що нам знадобиться це wgcf — is an unofficial, cross-platform CLI for Cloudflare Warp. Якщо ліниво збирати вручну то можна взяти готовий реліз під свою платформу. У мене wgcf_2.2.29_linux_amd64:

$ wget -O wgcf https://github.com/ViRb3/wgcf/releases/download/v2.2.29/wgcf_2.2.29_linux_amd64
$ chmod +x wgcf

Створимо конфігурацію для CloudFlare:

$ ./wgcf register --accept-tos --name HomeVPN

При цьому буде створено файл wgcf-account.toml, який містиме первинну конфігурацію.

В тому випадку якщо вже маємо ліцензію з оплаченим акаунтом (проте це не обов'язкова умова) можна оновити конфігурацію використовуючи наявний ключ.

./wgcf update --license-key QB………………-……………………-……………30H

Проте майте на увазі, що до одного акаунта може бути прив'язано не більше п'яти пристроїв. Якщо їх більше — виконання wgcf завершиться з помилкою.

Все, що нам залишилося це згенерувати текстовий файл конфігурації, щоб використовувати в подальшому наведені в ньому значення:

$ ./wgcf generate
2025/08/26 07:58:59 Using config file: wgcf-account.toml
2025/08/26 07:59:00 Successfully generated WireGuard profile: wgcf-profile.conf

Тепер ми маємо wgcf-profile.conf:

$ cat wgcf-profile.conf
[Interface]
PrivateKey = AGX……………………………………………………………………………………………………1g=
Address = 172.…….….…/32, 2606:…………:………:…………:…………:…………:…………:…………/128
DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
MTU = 1280
[Peer]
PublicKey = bmX…………………………………………………………………………………………………gyo=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = engage.cloudflareclient.com:2408

В першу чергу нас цікавитиме параметр PrivateKey.

Можемо приступити до налаштування MikroTIK. Створюємо інтерфейс клієнта:

/interface wireguard add listen-port=13231 mtu=1290 name=cloudflare-warp private-key="AGX……………………………………………………………………………………………………1g="

Налаштовуємо peer-параметри, всі значення беремо з wgcf-profile.conf:

/interface wireguard peers add allowed-address=0.0.0.0/0,::/0 endpoint-address=engage.cloudflareclient.com endpoint-port=2408 interface=cloudflare-warp name=cloudflare-peer public-key="bmX…………………………………………………………………………………………………gyo="
Ну і далі доволі стандартні кроки:
/interface list add comment=Internet name=INTERNET
/interface list member add interface=cloudflare-warp list=INTERNET
/ip firewall nat add action=masquerade chain=srcnat out-interface=cloudflare-warp
/routing table add disabled=no fib name=to-cloudflare
/ip address add address=172.…….….…/30 interface=cloudflare-warp
/ipv6 address add address=2606:…………:………:…………:…………:…………:…………:…………/128 advertise=no interface=cloudflare-warp
/ip route add dst-address=0.0.0.0/0 gateway=172.…….….1 routing-table=to-cloudflare
/ip firewall address-list add address=192.168.88.254 comment=og-home list=TO-CF-SRC
/ip firewall mangle add action=mark-connection chain=prerouting connection-mark=no-mark dst-address-list=TO-CF-SRC in-interface-list=LAN new-connection-mark=CF-conn
/ip firewall mangle add action=mark-connection chain=prerouting connection-mark=no-mark in-interface-list=LAN new-connection-mark=CF-conn src-address-list=TO-CF-SRC
/ip firewall mangle add action=mark-routing chain=prerouting connection-mark=CF-conn in-interface-list=LAN new-routing-mark=to-cloudflare
Ну от начебто і все. Всі інші налаштування — на власний самак ;)

вівторок, 18 лютого 2025 р.

Обмеження швидкості на етапі видачі ip-адреси DHCP-сервером в MikroTIK

Час від часу було необхідно обмежити швидкість тим чи іншим клієнтам локальної мережі, які отримують адресу по DHCP.

Що робили?

По-перше, створювали чергу для локальної мережі, наприклад так:

/queue simple add burst-limit=200M/200M burst-threshold=2M/2M burst-time=5s/5s max-limit=198M/198M name=lan queue=pcq-upload-src/pcq-download-dst target=bridge-local total-queue=pcq-dst-src

По-друге, фіксували за mac-адресою ту чи іншу ip-адресу. По-третє, створювали чергу, яку через parent підв'язували до створеної черги локальної мережі і обмежували швидкість для саме цієї ip-адреси.

Така схема робоча, але не дуже зручна, коли треба обмежити швидкість, скажемо так, масово.

Припустимо купуємо у провайдера 100 мегабіт. У нас 10 робочих місць. Задача - кожному роздати по 10 мегабіт.

Звісно можна зафіксувати адреси, а можна…

Варіант 1. Старе рішення.

Перший варіант, який приходить на думку: обійти таблицю leases і під кожну виділену ip-адресу створити відповідне правило в черзі. Це вирішується якось так (позичено і перероблено з форуму MikroTIK):

/ip dhcp-server lease
:foreach x in=[find] do={
 
    # grab variables for use below
    :local leaseaddr ([get $x address])
    :local leasemacaddr [get $x mac-address]
    :local leasehostname [get $x host-name]
    :local leasename [get $x comment]
    :local queuecomment

    :local minlimit 192.168.100.20
    :local maxlimit 192.168.100.100
 
    :local leaseinqueue false
 
    /queue simple
    :foreach y in=[find] do={
 
        #grab variables for use below
        :local queuetargetaddr [get $y target]
        :set queuecomment [get $y comment]
 
        # Isolate information  from the comment field (MAC, Hostname)
        :local queuemac [:pick $queuecomment 4 21]
        :local queuehostname [:pick $queuecomment 22 [:len $queuecomment]]
 
        # If MAC from lease matches the queue MAC then refresh the queue item
        :if ($queuemac = $leasemacaddr) do={
            # build a comment field
            :set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)

            set $y target=$leaseaddr comment=$queuecomment
            :if ($leasename != "") do= {
                set $y name=($leasename . " (" . $leasemacaddr . ")")
            } else= {
                :if ($leasehostname != "") do= {
                    set $y name=($leasehostname . " (" . $leasemacaddr . ")")
                } else= {
                    set $y name=$leasemacaddr
                }
            }
            :set leaseinqueue true
        } else= {
            # if ip exists for this lease but mac is different then update mac/hostname and reset counter
            :if ($queuetargetaddr = $leaseaddr) do={
                # build a comment field
                :set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
 
                set $y comment=$queuecomment
                reset-counters $y
                :if ($leasename != "") do= {
                    set $y name=($leasename . " (" . $leasemacaddr . ")")
                } else= {
                    :if ($leasehostname != "") do= {
                        set $y name=($leasehostname . " (" . $leasemacaddr . ")")
                    } else= {
                        set $y name=$leasemacaddr
                    }
                }
                :set leaseinqueue true
            }
        }
    }
 
    # There was not an existing entry so add one for this lease
    :if ($leaseinqueue = false) do={
        # build a comment field
        :set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
        # build command
        :local cmd "/queue simple add parent=lan target=$leaseaddr max-limit=100M/100M comment=$queuecomment"
        :if ($leasename != "") do={ 
            :set cmd "$cmd name=\"$leasename ($leasemacaddr)\"" 
        } else= {
            :if ($leasehostname != "") do={
                :set cmd "$cmd name=\"$leasehostname ($leasemacaddr)\""
            } else= {
                :set cmd "$cmd name=\"$leasemacaddr\""
            }
        }
 
        # If within the range is executed
        :if ($leaseaddr >= $minlimit && $leaseaddr <= $maxlimit) do={
            :execute $cmd
        }
    }
}
 
# Cleanup Routine - remove dynamic entries that no longer exist in the lease table
/queue simple
:foreach z in=[find] do={
    :local queuecomment [get $z comment]
    :local queue1stpart [:pick $queuecomment 0 3]
    :local queue2ndpart [:pick $queuecomment 4 21]
    :if ( $queue1stpart = "dtq") do={
        :if ( [/ip dhcp-server lease find mac-address=$queue2ndpart] = "") do={
            :log info ("DTQ: Removing stale entry for MAC Address - " . $queue2ndpart)
            remove $z
        }
    }
}

Це дійсно працює. Цей скрипт можна додати в Scheduler і насолоджуватися його роботою. Звісно за необхідності варто змінити на свій смак встановлення локальної змінної cmd.

Цей метод працює на будь-яких версіях RouterOS (правда на дуже старих не перевіряв, але має працювати, бо тут нічого складного і специфічного немає.

Явним недоліком є саме необхідність використання Scheduler, щоб підтримувати черги в актуальному стані.

Про те є інший, більш елегантний метод. Більш легкий метод.

Варіант 2. Lease Script.

В WinBox (або в WebFig, кому як подобається) переходимо в IP → DHCP Server. Відкриваємо налаштування свого DHCP. Переходимо у вкладку Script. Тут у нас велике поле для Lease Script, який буде виглядати приблизно так:

:local queueName "lan-$leaseActIP-$leaseActMAC";
:if ($leaseBound = "1") do={
    :log info "DHCP Lease START: $queueName"
    :local hostName [/ip dhcp-server lease get [find where active-mac-address=$leaseActMAC && active-address=$leaseActIP] host-name]
    /queue simple add burst-limit=50M/50M burst-threshold=1M/1M burst-time=5s/5s max-limit=49M/49M total-burst-limit=50M total-burst-threshold=1M total-burst-time=5s total-limit-at=48M total-max-limit=49M total-queue=pcq-dst-src name=$queueName parent=lan target=($leaseActIP . "/32") comment="$leaseActIP [ $leaseActMAC ] $hostName";
} else={
    :log info "DHCP Lease STOP: $queueName"
    /queue simple remove $queueName
}

І все. Скрипт викликається DHCP-сервером коли він «видає» або «забирає» ip-адресу. Відповідним чином встановлюється змінн $leaseBound, коли сервер видає адресу вона дорівнює "1".

Звісно, що тут можна додати й інші умови, інші виключення, тощо. Можна зробити й іншу структуру самих черг. Але, сподіваюся, що все й без того прозоро й зрозуміло. Користуймося.