fix(launcher): упростить пробы MikroTik до переменной vt-srcIp
Docker / build (push) Failing after 26s

Убраны автоопределение интерфейса и policy routing: исходный IP задаётся вручную на каждом роутере.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-08-26 10:55:17 +07:00
co-authored by Cursor
parent 72aad059bd
commit ecd053b832
6 changed files with 40 additions and 312 deletions
+12 -148
View File
@@ -1,17 +1,14 @@
# VPS Tracker — blocking launcher for RouterOS 7.22+
# First run: :global vtIface "ether1"; /tool fetch url="__VT_API_URL__/cc.rsc" dst-path=vt-cc.rsc; /import file-name=vt-cc.rsc
# Optional: :global vtGw "x.x.x.x" if the WAN gateway is not DHCP / not .1 of the subnet.
# First run: :global vt-srcIp "1.2.3.4"; /tool fetch url="__VT_API_URL__/cc.rsc" dst-path=vt-cc.rsc; /import file-name=vt-cc.rsc
# HTTPS GET only (no DPI/SNI). Ingest: POST /api/integrations/censorcheck/runs
:local vtApi "__VT_API_URL__"
:local vtToken "__VT_INGEST_TOKEN__"
:local vtDaily "__VT_DAILY__"
:local vtRemove "__VT_REMOVE_DAILY__"
:local launcherVer "ros-3"
:local launcherVer "ros-4"
:local schedName "vt-cc"
:local dstFile "vt-cc.rsc"
:local rtName "vt-cc"
:local rtComment "vt-cc-probe"
:local ver [/system resource get version]
:local dot [:find $ver "."]
@@ -32,142 +29,22 @@
:if ($vtRemove = "yes") do={
:do { /system scheduler remove [find name=$schedName] } on-error={}
:do { /ip firewall mangle remove [find comment=$rtComment] } on-error={}
:do { /ip firewall nat remove [find comment=$rtComment] } on-error={}
:do { /routing rule remove [find comment=$rtComment] } on-error={}
:do { /ip route remove [find comment=$rtComment] } on-error={}
:put ("Ежедневная проверка снята (" . $schedName . ")")
} else={
:put ("censorcheck launcher " . $launcherVer . " (RouterOS)")
:global vtIface
:if (([:typeof $vtIface] != "str") or ([:len $vtIface] = 0)) do={
:put "Задайте интерфейс и повторите импорт:"
:put ":global vtIface \"ether1\""
:put "Интерфейсы:"
/interface print
:error "vtIface не задан"
}
:if ([:len [/interface find where name=$vtIface]] = 0) do={
:put "Интерфейсы:"
/interface print
:error ("Нет интерфейса " . $vtIface)
}
:local srcIp ""
:local addrRaw
:local slash
:local pfxLen 0
:local net
:foreach a in=[/ip address find where interface=$vtIface] do={
:if ([:len $srcIp] = 0) do={
:set addrRaw [/ip address get $a address]
:set slash [:find $addrRaw "/"]
:if ([:typeof $slash] != "nil") do={
:set srcIp [:pick $addrRaw 0 $slash]
:set pfxLen [:tonum [:pick $addrRaw ($slash + 1) [:len $addrRaw]]]
} else={
:set srcIp $addrRaw
}
}
}
:if ([:len $srcIp] = 0) do={
:error ("Нет IPv4 на интерфейсе " . $vtIface)
}
:put ("интерфейс: " . $vtIface . " src=" . $srcIp)
:local gw ""
:local itype ""
:local igw
:local needle
:local fnd
:local gwy
:local failMsg ""
:local after
:do { /ip firewall mangle remove [find comment=$rtComment] } on-error={}
:do { /ip firewall nat remove [find comment=$rtComment] } on-error={}
:do { /routing rule remove [find comment=$rtComment] } on-error={}
:do { /ip route remove [find comment=$rtComment] } on-error={}
:do { /routing table add name=$rtName fib } on-error={}
:if ([:len [/ip dhcp-client find where interface=$vtIface]] > 0) do={
:do { :set gw [/ip dhcp-client get [find interface=$vtIface] gateway] } on-error={}
}
:if ([:len $gw] = 0) do={
:foreach rte in=[/ip route find where active] do={
:if ([:len $gw] = 0) do={
:set igw [/ip route get $rte immediate-gw]
:if ([:typeof $igw] = "str") do={
:set needle ("%" . $vtIface)
:set fnd [:find $igw $needle]
:if ([:typeof $fnd] != "nil") do={
:set after ($fnd + [:len $needle])
:if (($after = [:len $igw]) or ([:pick $igw $after ($after + 1)] = " ")) do={
:set gw [:pick $igw 0 $fnd]
}
}
}
:if ([:len $gw] = 0) do={
:set gwy [/ip route get $rte gateway]
:if (([:typeof $gwy] = "str") and ($gwy = $vtIface)) do={
:set gw $vtIface
}
}
}
}
}
:if ([:len $gw] = 0) do={
:do { :set itype [/interface get [find name=$vtIface] type] } on-error={}
:if (($itype = "pppoe-out") or ($itype = "pptp-out") or ($itype = "l2tp-out") or ($itype = "sstp-out") or ($itype = "ovpn-out") or ($itype = "wireguard")) do={
:set gw $vtIface
}
}
:if (([:len $gw] = 0) and ($pfxLen > 0) and ($pfxLen <= 30)) do={
:foreach a in=[/ip address find where interface=$vtIface] do={
:if ([:len $gw] = 0) do={
:do {
:set net [/ip address get $a network]
:set gw [:tostr ([:toip $net] + 1)]
} on-error={}
}
}
}
:global vtGw
:if (([:typeof $vtGw] = "str") and ([:len $vtGw] > 0)) do={
:set gw $vtGw
}
:if ([:len $gw] = 0) do={
:set gw $vtIface
}
:put ("шлюз: " . $gw)
:do {
/ip route add dst-address=0.0.0.0/0 gateway=$gw routing-table=$rtName pref-src=$srcIp comment=$rtComment
} on-error={
:do {
/ip route add dst-address=0.0.0.0/0 gateway=($gw . "%" . $vtIface) routing-table=$rtName pref-src=$srcIp comment=$rtComment
} on-error={
:set failMsg ("Не удалось добавить маршрут через " . $gw)
}
}
:if ([:len $failMsg] = 0) do={
:do {
/ip firewall mangle add chain=output action=mark-routing new-routing-mark=$rtName src-address=$srcIp passthrough=no comment=$rtComment place-before=0
} on-error={
/ip firewall mangle add chain=output action=mark-routing new-routing-mark=$rtName src-address=$srcIp passthrough=no comment=$rtComment
}
:do {
/routing rule add src-address=($srcIp . "/32") action=lookup-only-in-table table=$rtName comment=$rtComment
} on-error={}
:do {
/ip firewall nat add chain=srcnat action=accept src-address=$srcIp comment=$rtComment place-before=0
} on-error={
/ip firewall nat add chain=srcnat action=accept src-address=$srcIp comment=$rtComment
}
:global "vt-srcIp"
:if (([:typeof $"vt-srcIp"] != "str") or ([:len $"vt-srcIp"] = 0)) do={
:put "Задайте исходный IP и повторите импорт:"
:put ":global vt-srcIp \"1.2.3.4\""
:error "vt-srcIp не задан"
}
:local srcIp $"vt-srcIp"
:put ("vt-srcIp: " . $srcIp)
:local r
:local publicIp ""
:if ([:len $failMsg] = 0) do={
:do {
:set r [/tool fetch url="https://api.ipify.org" src-address=$srcIp output=user as-value]
:if (($r->"status") = "finished") do={
@@ -191,8 +68,8 @@
:if ([:typeof $lf] != "nil") do={ :set publicIp [:pick $publicIp 0 $lf] }
}
:if ([:len $publicIp] = 0) do={
:set failMsg "Не удалось определить публичный IP"
} else={
:error "Не удалось определить публичный IP"
}
:local hoster ""
:do {
@@ -210,9 +87,6 @@
:local runId ("mt-" . [:rndstr length=16])
:put ("probe IP: " . $publicIp)
:if ($publicIp != $srcIp) do={
:put ("внимание: probe IP " . $publicIp . " != src " . $srcIp)
}
:if ([:len $hoster] > 0) do={ :put ("хостер: " . $hoster) }
:put ("runId: " . $runId)
:put "Проверяю сайты (HTTPS GET, без DPI)..."
@@ -301,7 +175,7 @@
:if ($hour < 10) do={ :set hh ("0" . $hour) }
:if ($minute < 10) do={ :set mm ("0" . $minute) }
:local startTime ($hh . ":" . $mm . ":00")
:local ev (":global vtIface \"" . $vtIface . "\"; /tool fetch url=" . $vtApi . "/cc.rsc dst-path=" . $dstFile . "; /import file-name=" . $dstFile)
:local ev (":global vt-srcIp \"" . $srcIp . "\"; /tool fetch url=" . $vtApi . "/cc.rsc dst-path=" . $dstFile . "; /import file-name=" . $dstFile)
:do { /system scheduler remove [find name=$schedName] } on-error={}
/system scheduler add name=$schedName interval=1d start-time=$startTime on-event=$ev policy=read,write,test,policy comment="vps-tracker vt-cc"
:put ("Ежедневная проверка: каждый день в " . $startTime . " (" . $schedName . ")")
@@ -309,13 +183,3 @@
}
}
}
:do { /ip firewall mangle remove [find comment=$rtComment] } on-error={}
:do { /ip firewall nat remove [find comment=$rtComment] } on-error={}
:do { /routing rule remove [find comment=$rtComment] } on-error={}
:do { /ip route remove [find comment=$rtComment] } on-error={}
:if ([:len $failMsg] > 0) do={ :error $failMsg }
}
+12 -148
View File
@@ -1,17 +1,14 @@
# VPS Tracker — GeoIP launcher for RouterOS 7.22+
# First run: :global vtIface "ether1"; /tool fetch url="__VT_API_URL__/ic.rsc" dst-path=vt-ic.rsc; /import file-name=vt-ic.rsc
# Optional: :global vtGw "x.x.x.x" if the WAN gateway is not DHCP / not .1 of the subnet.
# First run: :global vt-srcIp "1.2.3.4"; /tool fetch url="__VT_API_URL__/ic.rsc" dst-path=vt-ic.rsc; /import file-name=vt-ic.rsc
# Primary GeoIP JSON + Cloudflare CDN. Ingest: POST /api/integrations/ipregion/runs
:local vtApi "__VT_API_URL__"
:local vtToken "__VT_INGEST_TOKEN__"
:local vtDaily "__VT_DAILY__"
:local vtRemove "__VT_REMOVE_DAILY__"
:local launcherVer "ros-3"
:local launcherVer "ros-4"
:local schedName "vt-ic"
:local dstFile "vt-ic.rsc"
:local rtName "vt-ic"
:local rtComment "vt-ic-probe"
:local ver [/system resource get version]
:local dot [:find $ver "."]
@@ -32,145 +29,25 @@
:if ($vtRemove = "yes") do={
:do { /system scheduler remove [find name=$schedName] } on-error={}
:do { /ip firewall mangle remove [find comment=$rtComment] } on-error={}
:do { /ip firewall nat remove [find comment=$rtComment] } on-error={}
:do { /routing rule remove [find comment=$rtComment] } on-error={}
:do { /ip route remove [find comment=$rtComment] } on-error={}
:put ("Ежедневная проверка снята (" . $schedName . ")")
} else={
:put ("ipregion launcher " . $launcherVer . " (RouterOS)")
:global vtIface
:if (([:typeof $vtIface] != "str") or ([:len $vtIface] = 0)) do={
:put "Задайте интерфейс и повторите импорт:"
:put ":global vtIface \"ether1\""
:put "Интерфейсы:"
/interface print
:error "vtIface не задан"
}
:if ([:len [/interface find where name=$vtIface]] = 0) do={
:put "Интерфейсы:"
/interface print
:error ("Нет интерфейса " . $vtIface)
}
:local srcIp ""
:local addrRaw
:local slash
:local pfxLen 0
:local net
:foreach a in=[/ip address find where interface=$vtIface] do={
:if ([:len $srcIp] = 0) do={
:set addrRaw [/ip address get $a address]
:set slash [:find $addrRaw "/"]
:if ([:typeof $slash] != "nil") do={
:set srcIp [:pick $addrRaw 0 $slash]
:set pfxLen [:tonum [:pick $addrRaw ($slash + 1) [:len $addrRaw]]]
} else={
:set srcIp $addrRaw
}
}
}
:if ([:len $srcIp] = 0) do={
:error ("Нет IPv4 на интерфейсе " . $vtIface)
}
:put ("интерфейс: " . $vtIface . " src=" . $srcIp)
:local gw ""
:local itype ""
:local igw
:local needle
:local fnd
:local gwy
:local failMsg ""
:local after
:do { /ip firewall mangle remove [find comment=$rtComment] } on-error={}
:do { /ip firewall nat remove [find comment=$rtComment] } on-error={}
:do { /routing rule remove [find comment=$rtComment] } on-error={}
:do { /ip route remove [find comment=$rtComment] } on-error={}
:do { /routing table add name=$rtName fib } on-error={}
:if ([:len [/ip dhcp-client find where interface=$vtIface]] > 0) do={
:do { :set gw [/ip dhcp-client get [find interface=$vtIface] gateway] } on-error={}
}
:if ([:len $gw] = 0) do={
:foreach rte in=[/ip route find where active] do={
:if ([:len $gw] = 0) do={
:set igw [/ip route get $rte immediate-gw]
:if ([:typeof $igw] = "str") do={
:set needle ("%" . $vtIface)
:set fnd [:find $igw $needle]
:if ([:typeof $fnd] != "nil") do={
:set after ($fnd + [:len $needle])
:if (($after = [:len $igw]) or ([:pick $igw $after ($after + 1)] = " ")) do={
:set gw [:pick $igw 0 $fnd]
}
}
}
:if ([:len $gw] = 0) do={
:set gwy [/ip route get $rte gateway]
:if (([:typeof $gwy] = "str") and ($gwy = $vtIface)) do={
:set gw $vtIface
}
}
}
}
}
:if ([:len $gw] = 0) do={
:do { :set itype [/interface get [find name=$vtIface] type] } on-error={}
:if (($itype = "pppoe-out") or ($itype = "pptp-out") or ($itype = "l2tp-out") or ($itype = "sstp-out") or ($itype = "ovpn-out") or ($itype = "wireguard")) do={
:set gw $vtIface
}
}
:if (([:len $gw] = 0) and ($pfxLen > 0) and ($pfxLen <= 30)) do={
:foreach a in=[/ip address find where interface=$vtIface] do={
:if ([:len $gw] = 0) do={
:do {
:set net [/ip address get $a network]
:set gw [:tostr ([:toip $net] + 1)]
} on-error={}
}
}
}
:global vtGw
:if (([:typeof $vtGw] = "str") and ([:len $vtGw] > 0)) do={
:set gw $vtGw
}
:if ([:len $gw] = 0) do={
:set gw $vtIface
}
:put ("шлюз: " . $gw)
:do {
/ip route add dst-address=0.0.0.0/0 gateway=$gw routing-table=$rtName pref-src=$srcIp comment=$rtComment
} on-error={
:do {
/ip route add dst-address=0.0.0.0/0 gateway=($gw . "%" . $vtIface) routing-table=$rtName pref-src=$srcIp comment=$rtComment
} on-error={
:set failMsg ("Не удалось добавить маршрут через " . $gw)
}
}
:if ([:len $failMsg] = 0) do={
:do {
/ip firewall mangle add chain=output action=mark-routing new-routing-mark=$rtName src-address=$srcIp passthrough=no comment=$rtComment place-before=0
} on-error={
/ip firewall mangle add chain=output action=mark-routing new-routing-mark=$rtName src-address=$srcIp passthrough=no comment=$rtComment
}
:do {
/routing rule add src-address=($srcIp . "/32") action=lookup-only-in-table table=$rtName comment=$rtComment
} on-error={}
:do {
/ip firewall nat add chain=srcnat action=accept src-address=$srcIp comment=$rtComment place-before=0
} on-error={
/ip firewall nat add chain=srcnat action=accept src-address=$srcIp comment=$rtComment
}
:global "vt-srcIp"
:if (([:typeof $"vt-srcIp"] != "str") or ([:len $"vt-srcIp"] = 0)) do={
:put "Задайте исходный IP и повторите импорт:"
:put ":global vt-srcIp \"1.2.3.4\""
:error "vt-srcIp не задан"
}
:local srcIp $"vt-srcIp"
:put ("vt-srcIp: " . $srcIp)
:local r
:local j
:local isp
:local org
:local publicIp ""
:if ([:len $failMsg] = 0) do={
:do {
:set r [/tool fetch url="https://api.ipify.org" src-address=$srcIp output=user as-value]
:if (($r->"status") = "finished") do={
@@ -194,8 +71,8 @@
:if ([:typeof $lf] != "nil") do={ :set publicIp [:pick $publicIp 0 $lf] }
}
:if ([:len $publicIp] = 0) do={
:set failMsg "Не удалось определить публичный IP"
} else={
:error "Не удалось определить публичный IP"
}
:local hoster ""
:do {
@@ -213,9 +90,6 @@
:local runId ("mt-" . [:rndstr length=16])
:put ("probe IP: " . $publicIp)
:if ($publicIp != $srcIp) do={
:put ("внимание: probe IP " . $publicIp . " != src " . $srcIp)
}
:if ([:len $hoster] > 0) do={ :put ("хостер: " . $hoster) }
:put ("runId: " . $runId)
:put "Проверяю GeoIP (JSON, IPv4)..."
@@ -418,7 +292,7 @@
:if ($hour < 10) do={ :set hh ("0" . $hour) }
:if ($minute < 10) do={ :set mm ("0" . $minute) }
:local startTime ($hh . ":" . $mm . ":00")
:local ev (":global vtIface \"" . $vtIface . "\"; /tool fetch url=" . $vtApi . "/ic.rsc dst-path=" . $dstFile . "; /import file-name=" . $dstFile)
:local ev (":global vt-srcIp \"" . $srcIp . "\"; /tool fetch url=" . $vtApi . "/ic.rsc dst-path=" . $dstFile . "; /import file-name=" . $dstFile)
:do { /system scheduler remove [find name=$schedName] } on-error={}
/system scheduler add name=$schedName interval=1d start-time=$startTime on-event=$ev policy=read,write,test,policy comment="vps-tracker vt-ic"
:put ("Ежедневная проверка: каждый день в " . $startTime . " (" . $schedName . ")")
@@ -426,13 +300,3 @@
}
}
}
:do { /ip firewall mangle remove [find comment=$rtComment] } on-error={}
:do { /ip firewall nat remove [find comment=$rtComment] } on-error={}
:do { /routing rule remove [find comment=$rtComment] } on-error={}
:do { /ip route remove [find comment=$rtComment] } on-error={}
:if ([:len $failMsg] > 0) do={ :error $failMsg }
}