[1.79.0] - 2026-08-18
- ADDED: A WEB carrier for the MTProto proxy, which Telegram Desktop 7.1.1 reaches over ordinary HTTPS - a client on a network that blocks MTProxy and fake-TLS outright had no way in, because every transport b4 offered still opened a recognisable MTProto socket from the client. b4 answers a relay hostname with a bridge page the client loads in a hidden WebView, multiplexes the MTProxy stream through a same-origin WebSocket, and hands each logical stream to the same secrets, DC pool and upstream routing as a plain connection; requests without a valid bridge token get an ordinary page.
Settings > MTProto Proxy. - FIXED: A set's DNS redirect answered SERVFAIL for every domain it covered as soon as its DoH server went unreachable - the redirect had no fallback of any kind, so a resolver the censor happened to be blocking took the whole set offline while the bypass strategy underneath it was working perfectly well. b4 replays the last good answer or hands the query back to the resolver the client was already using, and a Fail closed switch under
Sets > Routing > DNS Redirectkeeps the old behaviour. - FIXED: Discovery offered a bypass strategy for domains that were never blocked - nothing in a run was compared against its own no-bypass fetch, so one blocked domain put a strategy on the whole batch, and the improvement percentage measured the site against yandex.ru, the reference domain b4 uses to gauge the line. Each domain is judged against its own unmodified fetch and reported on its own.
- FIXED: A Discovery strategy was declared working on one page fetch that may not have succeeded at all - only HTTP 451 counted as a failure, so a 502 longer than a kilobyte scored as a success, the probe negotiated HTTP/1.1 with no ALPN while every browser asks for HTTP/2, and a redirected page was scored over the address of the domain that redirected it. The winner is fetched three more times in the shape saving it as a set gives it, and one that fails any of those tries gives way to the next candidate.
- FIXED: On a router with working IPv6, Discovery stopped after about twenty tests and reported that no bypass was needed - its test connections were free to use either version of the protocol while b4 acts on IPv4 alone, so the opening test succeeded over a route nothing was interfering with.
- FIXED: Discovery built sets around a DNS redirect and geo categories the router had no use for - the redirect was stamped onto every set of a run as soon as one domain looked poisoned, though the probes never used it themselves, and geosite and geoip categories were carried in whatever was installed, so a result for a CDN domain could not be added at all without a geo database.
- FIXED: Restarting or stopping the service from the interface went wrong on systemd - b4 waited on a systemctl that systemd stops together with the service it is restarting, so every restart left
Restart command failed: signal: terminatedin the error log, and an unfinished browser connection could hold a stop open for the full ten seconds until the kill landed while the firewall cleanup was still running. - FIXED: An update could stop the service loading, or leave a second b4 running outside the service manager - the updater recognised every init system except systemd, so a unit written by anything other than b4's installer was rebuilt as a SysV init script, and it waited one second for the service to come back before starting b4 by hand, racing the manager's own restart.
- ADDED: A source allowlist for the SOCKS5 proxy, holding the IP addresses and CIDR ranges permitted to connect - the only control over who reached the proxy was a username and password, which Chrome and Chromium cannot send at all, so a LAN client on either browser meant leaving the proxy open to everything that could reach its port.
Settings > SOCKS5 Proxy. - FIXED: The SOCKS5 proxy served clients it was meant to keep out - a username without a password, or a password without a username, switched authentication off rather than failing, and the UDP relay took an address written into the associate request over the source of the control connection, so an association could be pointed at another host on the network.
- FIXED: Turning the SOCKS5 proxy off left the connections it was already carrying running - only the listener closed, so established tunnels kept relaying until the client dropped them by itself, and changing the port or the bind address behaved the same way.
- ADDED: A Block QUIC switch on a set's UDP tab, and a UDP action that leaves matched packets alone - pushing a browser off QUIC and back onto TCP took two settings in two places with nothing saying they belonged together, and every action a set could pick altered the traffic, so a set matching QUIC only to learn a site's addresses had to fake and fragment it anyway.
Sets > UDP. - CHANGED: Two of the three QUIC matching values did the same thing - one read as turning QUIC matching off and the other as merely parsing, while both matched the set by the server name in the ClientHello. They are one value, By SNI, and stored sets are converted on the first start.
- FIXED: An IPv6 packet carrying extension headers could crash b4 - a header claiming more bytes than the packet held sent the read past its end, stopping the service for every device on the router.
- ADDED: Force IPv4 for matched domains, which drops the IPv6 records from answers for names a set matched - b4 processes IPv4 only until IPv6 support is turned on, so a dual-stack site a set targets was reached over IPv6 and bypassed the set entirely.
Settings > Core > DNS. - FIXED: A DNS answer that b4 rewrote never cleared the failure count for that name - the answer was judged before the rewrite rather than after, so a site that had recovered was moved to its backup set on the next single failure.
- ADDED: An egress IP for a set, which replaces the source address of its traffic - a set could only be steered by naming an interface or an upstream SOCKS5 proxy, which a router that picks its path by source address cannot use.
Sets > Routing. - FIXED: A device added by hand was ignored everywhere devices are matched - such a device has no MAC address on the network, so a set bound to it stopped taking its route, block sets and the all-devices-except-selected option were disarmed, the filter under Settings, Device Filtering sat inert while routing kept applying to every device, and an MSS clamp on it clamped nothing while pulling every other forwarded connection down to the smallest configured size. Such devices are matched by the IP address entered for them.
- FIXED: A routing set limited to source devices diverted traffic it was never meant to touch - the rules on the router's own outgoing traffic carried no device filter, which paired with Match any IP address pulled its whole outbound path into the tunnel, and a set matched only by TCP or UDP port checked the port before any source at all while claiming its traffic was being diverted, which switched off every DPI countermeasure.
- FIXED: A routing set with no domain or IP target was built in full and quietly matched nothing - every routing rule matches a destination address, so a set with none could never match a packet, and nothing above trace level said so.
- CHANGED: Three unrelated services shared the API settings tab through a two-column grid and three different ways of showing a credential - the IPinfo token was a plain field, the AI key a panel of chips and buttons, the MCP token a full-width field printing the secret in clear, and each service's enable switch sat among the fields it governed. The tab is called Integrations and gives every service one card whose header carries its on/off switch, one masked credential field with reveal, copy and generate, and for MCP a client configuration block that copies the endpoint and token as a ready-made JSON snippet.
- FIXED: b4 took the router down after a few minutes on a busy line, leaving
runtime: program exceeds 10000-thread limitin the log - every matched packet started its own injection task with no ceiling, and those tasks wrote to a raw socket that had no send timeout, so an outgoing interface that stopped draining held one kernel thread per task until the Go runtime refused to create more. - ADDED: The operating system thread count on the dashboard Runtime card - the card reported goroutines but nothing about OS threads, which is the number the Go runtime stops the service over, so a runaway stayed invisible until the crash. b4 writes a goroutine dump to the log directory once the count passes half the limit.
What's Changed
- feat(routing): add Egress IP support for traffic source rewriting by @DanielLavrushin in #315
- feat: add strict mode for DNS resolution and implement fallback mecha… by @DanielLavrushin in #317
- feat: enhance settings page and UI components by @DanielLavrushin in #319
- refactor: simplify facet label handling and remove unused translations by @DanielLavrushin in #320
Full Changelog: v1.78.0...v1.79.0