Add daemon RPCs, Apple and GTK import flows, packet proxy runtime support, diagnostics, and BEPs for proxy subscription handling. Redact subscription URL secrets from fetch errors before they reach logs or UI surfaces.
26 KiB
Burrow vs Mihomo Trojan Implementation Discrepancies
Date: 2026-05-31
Scope: code-path comparison between the local Burrow checkout at
/Users/jettchen/dev/burrow and the local Mihomo checkout at
/Users/jettchen/dev/vpn-ref/mihomo. This is not based on current live system
network state.
Executive Summary
The most important differences for the stored Hong Kong Trojan node are:
- Mihomo uses
client-fingerprint: chromefor Trojan URIs when nofpquery is present and switches to uTLS when that fingerprint is configured. Burrow storesclient_fingerprintbut the Trojan runtime does not use it. - Mihomo distinguishes absent ALPN from explicitly empty ALPN. For Trojan TCP,
absent ALPN defaults to
["h2", "http/1.1"]; explicitly empty ALPN remains empty. Burrow now carries analpn_presentmarker for new imports and treats legacy missing metadata as absent. - Mihomo has a dedicated proxy-server DNS path (
proxy-server-nameserver/ProxyServerHostResolver). Burrow resolves proxy server names with the process/system resolver throughToSocketAddrs. - Mihomo preserves and reconstructs destination hostname metadata in fake-IP
and mapping modes. Burrow's packet runtime receives
SocketAddrvalues from its userspace stack and sends IP-form SOCKS addresses to Trojan, not domain names. - Mihomo supports Trojan
tcp,ws, andgrpcruntimes, plus additional TLS features such as ECH, REALITY, pinned certificate fingerprint, and optional Trojan-over-Shadowsocks wrapping. Burrow parses some of that metadata but the packet runtime only supports Trojan TCP. - Mihomo's dial path has timeout, retry, dual-stack fallback, optional parallel dialing, interface/routing-mark controls, DNS cache/fallback, and UDP fragmentation behavior. Burrow now matches Trojan UDP fragmentation, but its dial path remains a much narrower serial dialer plus a fixed packet bridge.
Implementation note:
BEP-0011and the current runtime patch address ALPN absence/defaulting, Trojan UDP import/runtime gating, Trojan UDP fragmentation, and certificate fingerprint pinning.- Burrow still does not implement Mihomo's uTLS/browser ClientHello impersonation, ws/grpc Trojan transports, REALITY/ECH, proxy-server DNS plane, fake-IP metadata, or policy/rule pipeline.
Stored Node Context
Current Burrow database state inspected from the app group DB:
network type: ProxySubscription
subscription: bitz
selected ordinal: 2
selected name: Hong Kong Guangdong BGP 2
protocol: trojan
server: ce1081d2-df04-48d7-80bf-46b8c50b4f33.bnsepserv.com
port: 32445
network: tcp
sni: pull-flv-q1-admin.douyincdn.com
skip_cert_verify: true
alpn: []
client_fingerprint: chrome
fingerprint: null
Evidence:
- Burrow stores Trojan node fields in
TrojanNode:password,sni,alpn,alpn_present,skip_cert_verify,network,udp,client_fingerprint, andfingerprint(burrow/src/proxy_subscription.rs:82). - The runtime
TrojanOutboundcarries endpoint, password, SNI, ALPN, skip-cert, UDP enablement, and parsed certificate fingerprint. It still does not applyclient_fingerprint.
1. Subscription and Config Parsing
Supported subscription shapes
Mihomo:
- Parses individual proxies through a generic adapter parser
(
adapter/parser.go:11). - For
type: trojan, decodes the fullTrojanOptionwith the common structure decoder and constructsNewTrojan(adapter/parser.go:79). - Supports proxy providers with
file,http, andinlinevehicles (adapter/provider/parser.go:77). - Provider schemas include filter, exclude-filter, exclude-type, dialer-proxy,
size-limit, headers, override, payload, health-check, and refresh interval
(
adapter/provider/parser.go:28).
Burrow:
- Parses either a top-level YAML
proxiesfield or a plaintext/base64 URI list (burrow/src/proxy_subscription.rs:235,burrow/src/proxy_subscription.rs:274,burrow/src/proxy_subscription.rs:312). - Does not parse Mihomo
proxy-providers,proxy-groups, provider refresh options, health-checks, overrides, or group selectors. - For URI-list content, only
trojan://andss://are accepted; other schemes become rejected entries (burrow/src/proxy_subscription.rs:323).
Impact:
- Burrow can import the selected node, but it does not preserve Mihomo's full provider/group behavior. Selection is Burrow-owned, not Mihomo group semantics.
URI conversion
Mihomo:
- Trojan URI conversion maps fragment to name, host/port/user to server/port/
password,
allowInsecuretoskip-cert-verify, optionalsni, optionalalpn, optionaltype, ws/grpc options,pcsto certificate fingerprint, andfptoclient-fingerprint(common/convert/converter.go:149). - The URI converter also sets
udp: truefor Trojan URI imports (common/convert/converter.go:162). - If
fpis absent, Mihomo setsclient-fingerprinttochrome(common/convert/converter.go:198).
Burrow:
- Maps similar basics and also defaults missing
fptochrome(burrow/src/proxy_subscription.rs:491). - Stores
pcsasfingerprint(burrow/src/proxy_subscription.rs:517). - Stores ALPN with an
alpn_presentmarker, so new imports can distinguish missing ALPN from explicit empty ALPN (burrow/src/proxy_subscription.rs:83).
Discrepancy:
- Mihomo can distinguish "ALPN field absent" from "ALPN field present but empty" at the decoded option/runtime layer because the option slice can be nil or non-nil. Burrow now records that distinction for new imports.
- Mihomo URI conversion only sets
alpnwhen the URI query value is non-empty; this is still different from Burrow because Burrow imports absent URI ALPN as a concrete empty vector that the runtime later treats as intentional. - Mihomo carries Trojan's
udpoption through the base outbound model. Burrow now stores the Trojanudpfield and gates Trojan UDP sessions on it.
2. Runtime Transport Support
Mihomo:
TrojanOption.Networksupports default TCP,ws, andgrpc(adapter/outbound/trojan.go:51).- Runtime branches:
ws: wraps the TCP connection in websocket over TLS (adapter/outbound/trojan.go:67).grpc: uses gun transport and a gRPC client pool (adapter/outbound/trojan.go:175,adapter/outbound/trojan.go:298).- default TCP: TLS, then Trojan header (
adapter/outbound/trojan.go:119).
- Trojan options also include
ECHOpts,RealityOpts,SSOpts, andClientFingerprint(adapter/outbound/trojan.go:52). - If
ss-opts.enabledis set, Mihomo wraps Trojan streams in Shadowsocks using the configured method/password, defaulting the method toAES-128-GCM(adapter/outbound/trojan.go:284).
Burrow:
- Parser represents
Tcp,Ws, andGrpc(burrow/src/proxy_subscription.rs:93). - Runtime rejects any Trojan network except
Tcp(burrow/src/proxy_runtime.rs:553). - Runtime preview can mark unsupported transports via
runtime_support_error(burrow/src/proxy_runtime.rs:279).
Discrepancy:
- Burrow parses ws/grpc metadata but cannot run ws/grpc Trojan nodes.
- Mihomo can run ws and grpc Trojan nodes.
- Burrow has no Trojan-over-Shadowsocks wrapper equivalent for Mihomo
ss-opts. - Burrow has no Trojan REALITY or ECH runtime support.
3. ALPN Behavior
Mihomo:
- Trojan TCP default ALPN is
["h2", "http/1.1"](transport/trojan/trojan.go:23). - For default TCP, Mihomo starts with that default, then overrides only if
option.ALPN != nil(adapter/outbound/trojan.go:122). - For websocket, default ALPN is
["http/1.1"]and is overridden only ifoption.ALPN != nil(adapter/outbound/trojan.go:95). - For grpc, TLS
NextProtosis fixed to["h2"](adapter/outbound/trojan.go:307).
Burrow:
- Runtime ALPN uses Mihomo's TCP default when
alpn_presentis false, and usesTrojanNode.alpnexactly whenalpn_presentis true (burrow/src/proxy_runtime.rs:695). - TLS config writes those strings directly into rustls
alpn_protocols(burrow/src/proxy_runtime.rs:820). - Parser stores missing ALPN as
alpn_present: false; legacy stored nodes that lackalpn_presentdeserialize the same way.
Discrepancy:
- For a Trojan URI that omits
alpn, Mihomo sendsh2,http/1.1; Burrow now applies the same default through the presence marker. - Explicit empty ALPN is possible through Mihomo's decoded YAML/options path,
but not through its URI converter because empty URI
alpnis not emitted.
Likely relevance:
- The selected node has
alpn: []in Burrow. If the subscription omitted ALPN, Mihomo would use the default ALPN list, while Burrow now cannot know that and sends none.
4. Client Fingerprint and uTLS
Mihomo:
- Trojan options include
ClientFingerprint(adapter/outbound/trojan.go:57). - URI conversion defaults missing
fptochrome(common/convert/converter.go:198). - TLS connection code checks
GetFingerprint; when recognized, it converts the TLS config to a uTLS config and creates a uTLS client (transport/vmess/tls.go:46). - uTLS preserves
NextProtos,ServerName, cert settings, and version bounds from the config (component/tls/utls.go:175). GetFingerprintfalls back to a global fingerprint if the node omits one, returns no uTLS for empty/none, supportsrandom, and recognizes browser profiles such aschrome,firefox,safari,ios,android,edge,360, andqq(component/tls/utls.go:42,component/tls/utls.go:65,component/tls/utls.go:81).- For websocket, Mihomo forces the uTLS ALPN extension to
http/1.1(component/tls/utls.go:258).
Burrow:
- Parser stores
client_fingerprint(burrow/src/proxy_subscription.rs:89). - Runtime logs it when present, but does not use it to build a uTLS ClientHello.
- Runtime uses OpenSSL on macOS and rustls/tokio-rustls elsewhere, not Mihomo's uTLS implementation.
Discrepancy:
- Mihomo sends a Chrome-like TLS ClientHello for this selected node
(
client_fingerprint: chrome). - Burrow sends the platform TLS stack's ClientHello.
Likely relevance:
- Many Trojan subscriptions use
fp=chromeor Mihomo's defaultchromebecause the server or fronting path expects that TLS fingerprint. Burrow ignoring it is a high-probability compatibility gap.
5. Certificate Verification and Pinning
Mihomo:
- Trojan options include
SkipCertVerify,Fingerprint,Certificate, andPrivateKey(adapter/outbound/trojan.go:46). - TLS setup passes those into
ca.GetTLSConfig(adapter/outbound/trojan.go:101,transport/vmess/tls.go:27). - URI conversion maps
pcstofingerprint(common/convert/converter.go:204). - Mihomo treats
fingerprintas SHA-256 certificate pinning. Browser names such aschromeare rejected there with an instruction to useclient-fingerprintinstead (component/ca/fingerprint.go:13). - A pinned fingerprint may match any certificate in the chain; if it matches a
non-leaf certificate, Mihomo verifies the leaf against that pinned certificate
as a trusted root (
component/ca/fingerprint.go:29). GetTLSConfiginstallsVerifyConnectionand setsInsecureSkipVerifywhen pinning is enabled, so Go's default verifier is bypassed in favor of the pin verifier (component/ca/config.go:100).- Mihomo supports TLS client certificates through
certificate/private-key, including inline material, safe file paths, file watching, or generated random key material when both are empty (component/ca/config.go:114,component/ca/keypair.go:25).
Burrow:
- Parser stores
fingerprint(burrow/src/proxy_subscription.rs:90). - Runtime parses
fingerprintas a SHA-256 certificate pin and checks the presented certificate chain against it (burrow/src/proxy_runtime.rs:865). - Runtime root store is webpki roots;
skip_cert_verifyinstalls a verifier that accepts the certificate/signature checks (burrow/src/proxy_runtime.rs:820,burrow/src/proxy_runtime.rs:835).
Discrepancy:
- Mihomo supports pinned certificate fingerprint and custom certificate material.
- Burrow now supports SHA-256 certificate fingerprint pinning, normal root validation, or all-cert skip verification.
- Burrow has no client certificate fields for Trojan.
6. SNI Behavior
Mihomo:
NewTrojandefaults empty SNI to the server host (adapter/outbound/trojan.go:251).- Trojan URI conversion sets SNI only when the
sniquery is present (common/convert/converter.go:168). - TLS config uses
option.SNIas host/server name (adapter/outbound/trojan.go:126).
Burrow:
- Parser accepts URI
sni,peer, orhostas SNI (burrow/src/proxy_subscription.rs:505). - Runtime defaults SNI to node server if absent
(
burrow/src/proxy_runtime.rs:561).
Discrepancy:
- Burrow accepts more SNI aliases in URI parsing than Mihomo's converter path.
- Runtime defaulting is effectively aligned for TCP.
7. Trojan Header and Password Hash
Mihomo:
- Password is converted with
trojan.Key(adapter/outbound/trojan.go:269). - Trojan header writes hex password, CRLF, command byte, SOCKS address, CRLF
(
transport/trojan/trojan.go:39). - TCP command is
1, UDP command is3(transport/trojan/trojan.go:31).
Burrow:
- Password hash is SHA-224 hex (
burrow/src/proxy_runtime.rs:903). - Header writes hash, CRLF, command byte, SOCKS address, CRLF as a single
coalesced buffer, matching Mihomo's one-write
trojan.WriteHeaderbehavior. - TCP uses command
0x01; UDP uses0x03(burrow/src/proxy_runtime.rs:583,burrow/src/proxy_runtime.rs:604).
Discrepancy:
- No remaining framing discrepancy for basic TCP/UDP header shape. A live provider check showed that splitting the Trojan TCP header across multiple TLS writes could produce EOF before any target response bytes; Burrow now coalesces the TCP header before writing it.
8. Destination Address and Hostname Metadata
Mihomo:
serializesSocksAddrwrites a domain-form SOCKS address whenmetadata.AddrType()is domain (adapter/outbound/util.go:15).- Fake-IP and mapping preprocessing can translate a destination fake IP back to
hostname, clear
DstIP, and markDNSFakeIP(tunnel/tunnel.go:287). - If fake-IP metadata is missing, Mihomo may sniff TCP to recover a domain
(
tunnel/tunnel.go:511).
Burrow:
- Netstack TCP accept yields
remote_addr: SocketAddr; Burrow now checks its daemon-owned fake-IP DNS cache and writes a domain-form SOCKS address when the accepted destination IP maps back to a hostname. It falls back to IP-form when no hostname is known. - UDP sessions key on local/remote
SocketAddr. DNS queries to Burrow's daemon-owned resolver are answered locally before they become proxy UDP flows. Other UDP flows still use socket-address metadata. - Burrow can parse a domain-form SOCKS address in Trojan UDP responses, but it
resolves that domain immediately through the process/system resolver and
returns a
SocketAddr(burrow/src/proxy_runtime.rs:1187). - Burrow has a basic fake-IP map for A queries answered by the daemon resolver, but no TCP sniffer or rules engine.
Discrepancy:
- Mihomo can preserve domain targets through fake-IP/mapping paths.
- Burrow now preserves DNS-backed domain targets for TCP, but only for domains resolved through its daemon-owned A-query fake DNS path.
Compatibility impact:
- For ordinary HTTPS this may still work because the application supplies TLS SNI to the target site. It breaks or weakens Mihomo-style rule selection, fake-IP DNS, and any proxy behavior that needs the destination hostname at the outbound layer.
9. Proxy Server DNS Resolution
Mihomo:
- The generic dialer resolves proxy server hostnames through
resolver.ProxyServerHostResolverby default (component/dialer/dialer.go:358). ProxyServerHostResolveris wired fromproxy-server-nameserverwhen present, otherwise from the normal resolver (hub/executor/executor.go:290).- Resolver lookup checks hosts first, IP literals second, then configured
resolver or system resolver fallback (
component/resolver/resolver.go:154). - DNS exchange uses cache, singleflight, retry monitor, main/fallback
nameservers, and policy routing (
dns/resolver.go:150,dns/resolver.go:220,dns/resolver.go:298). - Resolver caches are TTL based, can serve stale records with background refresh,
and use a default max size of 4096 (
dns/resolver.go:150,dns/resolver.go:452,dns/util.go:48). - The system resolver refreshes
/etc/resolv.confperiodically and can fall back to public DNS servers if no system DNS clients are available (dns/system_common.go:15,dns/system.go:68).
Burrow:
- Proxy endpoint resolution starts with
(host, port).to_socket_addrs()via the process/system resolver. - The current workspace caches resolved proxy server addresses in
ProxyServerEndpointwhen the outbound is configured (burrow/src/proxy_runtime.rs:1263). - If system DNS returns only
198.18.0.0/15fake-IP addresses, Burrow falls back to direct DNS using physical/public DNS servers and excludes the resolved real proxy-server host routes from the tunnel. - There is no user-configurable proxy-server resolver equivalent.
- There is no DNS TTL refresh or resolver cache for proxy server hosts beyond the current cached address list.
Discrepancy:
- Mihomo has a first-class proxy-server DNS plane; Burrow does not.
- Mihomo has richer policy and cache controls for proxy-server DNS. Burrow now
has a narrower fake-IP fallback that avoids recursive proxy-server dials for
observed
198.18.0.0/15answers.
10. Dialing Strategy, Interface Binding, and Socket Options
Mihomo:
- Dialer parses all resolved IPs, normalizes IPv4-in-IPv6, and supports IPv4/
IPv6 preference (
component/dialer/dialer.go:358). - It can dial serially, in dual-stack fallback mode, or in parallel depending on
tcpConcurrent(component/dialer/dialer.go:58,component/dialer/dialer.go:207). - Dialer applies keepalive and MPTCP settings (
component/dialer/dialer.go:139). - Dialer supports explicit
interface-name, default interface, interface finder, routing mark, TFO, MPTCP, and custom net dialers (component/dialer/dialer.go:143,adapter/outbound/base.go:145). - The dialer option model includes
interfaceName,fallbackBind,routingMark, preferred IP family, TFO, MPTCP, resolver, and custom net dialer (component/dialer/options.go:33). - Darwin interface binding uses
IP_BOUND_IF/IPV6_BOUND_IF(component/dialer/bind_darwin.go:14). - Linux interface binding uses bind-to-device, and Linux routing marks use
SO_MARK(component/dialer/bind_linux.go:12,component/dialer/mark_linux.go:20). - Mihomo wraps outbound connection creation in a 5 second context and a retry
loop with up to 10 attempts, stopping early for non-retryable DNS/reject
errors (
tunnel/tunnel.go:560,tunnel/tunnel.go:702). - The dialer has a 300 ms dual-stack fallback window and optional parallel dial
mode (
component/dialer/dialer.go:25,component/dialer/dialer.go:58,component/dialer/dialer.go:207).
Burrow:
- Dials cached addresses sequentially (
burrow/src/proxy_runtime.rs:1294). - No explicit TCP connect timeout wrapper is applied in this path.
- No TFO, MPTCP, routing mark, custom dialer, or configurable interface name.
- On Apple, Burrow chooses a default physical interface by scanning interfaces,
preferring
en*and skippingutun, loopback, bridge, awdl, etc. (burrow/src/proxy_runtime.rs:1501). - Burrow skips physical-interface binding for loopback proxy-server addresses so
controlled local proxy runtime tests can use
127.0.0.1. - On non-Apple,
bind_proxy_outbound_socketis a no-op (burrow/src/proxy_runtime.rs:1495).
Discrepancy:
- Mihomo has a mature, configurable dialer. Burrow has a narrow Apple-focused physical-interface bind path and a sequential dial loop.
- Burrow has no high-level per-flow retry loop comparable to Mihomo's tunnel retry.
11. UDP Behavior
Mihomo:
- Trojan supports UDP through
ListenPacketContext(adapter/outbound/trojan.go:202). - UDP exposure is gated by the node's
udpoption throughBase.SupportUDP(adapter/outbound/trojan.go:50,adapter/outbound/base.go:105). - Before UDP, it resolves destination metadata if needed
(
adapter/outbound/trojan.go:203,adapter/outbound/base.go:178). SupportUOTreturns true (adapter/outbound/trojan.go:225).- UDP packet handling maintains mappings from origin metadata to target address
(
tunnel/connection.go:70). - Trojan UDP packet writes fragment payloads larger than 8192 bytes into
multiple Trojan UDP frames (
transport/trojan/trojan.go:54,transport/trojan/trojan.go:66).
Burrow:
- UDP is enabled in the userspace netstack (
burrow/src/proxy_runtime.rs:379). - Burrow's import/runtime model has no Trojan
udpenable flag, so the runtime does not mirror Mihomo's per-node UDP gating. - UDP sessions are keyed by local/remote socket address and use a channel per
flow (
burrow/src/proxy_runtime.rs:516). - Trojan UDP opens a TLS connection per UDP flow, writes a Trojan UDP header,
and relays Trojan UDP packets over that stream
(
burrow/src/proxy_runtime.rs:598). - UDP flow idle timeout is 30 seconds (
burrow/src/proxy_runtime.rs:45). - No UOT support is exposed.
- Burrow now fragments single Trojan UDP payloads above 8192 bytes into multiple
Trojan UDP frames (
burrow/src/proxy_runtime.rs:1050). - Burrow now carries a Trojan
udpenable/disable flag.
Discrepancy:
- Mihomo has metadata-aware UDP resolution/mapping and UOT support. Burrow has direct per-flow Trojan UDP over TLS without hostname metadata.
- Mihomo and Burrow both fragment oversized Trojan UDP payloads after
BEP-0011.
12. Packet Tunnel and DNS Model
Mihomo:
- TUN mode has metadata preprocessing, fake-IP reverse mapping, sniffing, rule
resolution, and then proxy dial (
tunnel/tunnel.go:287,tunnel/tunnel.go:540). - DNS service and resolver enhancer support fake-IP/mapping modes
(
dns/service.go:27,dns/enhancer.go:23).
Burrow:
- Apple Network Extension forwards packets to a daemon packet stream and writes
daemon responses back to
packetFlow(Apple/NetworkExtension/PacketTunnelProvider.swift:91). - Burrow's proxy tunnel settings use virtual addresses and point DNS at the
daemon-owned resolver address
100.64.0.2. - The daemon answers A queries with stable fake IPs and records fake-IP to hostname mappings for later TCP proxy requests. There is still no rules engine or TCP sniffer in the packet runtime.
Discrepancy:
- Mihomo is a policy-aware packet tunnel with DNS hijack/fake-IP metadata.
- Burrow is a simpler packet-to-selected-outbound bridge with daemon-owned fake DNS for A queries. It does not yet implement Mihomo's policy routing, sniffing, resolver modes, or per-rule metadata pipeline.
13. Logging and Observability
Mihomo:
- DNS cache hits, DNS resolution, metadata preprocessing failures, process lookup
failures, and UDP resolution failures are logged in the relevant paths
(
dns/resolver.go:170,tunnel/tunnel.go:339,tunnel/tunnel.go:506,tunnel/connection.go:88).
Burrow:
- Runtime now logs selected node, configured Trojan outbound metadata, resolved
proxy addresses, fake-IP/benchmark-range warning, and socket bind/connect
failures (
burrow/src/proxy_runtime.rs:215,burrow/src/proxy_runtime.rs:552,burrow/src/proxy_runtime.rs:1263,burrow/src/proxy_runtime.rs:1294). Scripts/burrow-proxy-selftestprovides a controlled daemon packet-runtime test against a local Trojan server, andproxy-tcp-probe --dns-nameexercises daemon DNS plus raw TCP packet streaming without changing system proxy state.- On macOS, Rust tracing goes to stderr by default; OSLog is opt-in via
BURROW_ENABLE_OSLOG=1(burrow/src/tracing.rs:50).
Discrepancy:
- Mihomo logs more of the full metadata/rule/DNS pipeline.
- Burrow now logs the outbound path and has standalone packet-runtime probes, but still lacks Mihomo's full metadata/rule diagnostics.
14. Likely Compatibility Gaps for the Selected Node
Highest probability:
client_fingerprint: chromeis stored but not implemented by Burrow runtime. Mihomo would use uTLS Chrome, so this remains a compatibility gap for providers that strictly require browser ClientHello impersonation.- The selected provider node succeeds through Mihomo when Mihomo is configured
from Burrow's stored DB payload, pinned to real proxy-server IPs, and bound to
en0. Burrow's daemon packet probe now also succeeds forgoogle.com:80after macOS OpenSSL TLS and coalesced Trojan header writes. - Older stored nodes may have
alpn: []from pre-BEP-0011imports. Burrow now treats missingalpn_presentas absent ALPN and applies Mihomo's TCP default. - Burrow's proxy-server resolver is narrower than Mihomo's configurable proxy-server DNS plane.
Medium probability:
- Burrow only preserves domain metadata for TCP flows that went through its daemon-owned A-query fake DNS path.
- Burrow has no Mihomo-style sniffing or rule metadata. This is less likely to break simple all-traffic proxying, but it is a major semantic difference.
Lower probability for this exact selected node:
- ws/grpc transport is unsupported by Burrow runtime. The selected node is TCP, so this is not the immediate failure for that node.
- Certificate pinning is now implemented by Burrow. The selected node has no stored pinned fingerprint, so this does not explain that exact node.
Suggested Burrow Follow-Ups
- Implement
client_fingerprintfor Trojan, at leastchrome, or reject nodes requiring runtime fingerprints until uTLS-style support exists. - Expand the proxy-server resolver path toward Mihomo's configurable
proxy-server-nameserverbehavior and TTL/cache controls. - Add sniffing or broader DNS metadata handling for flows that do not use the daemon-owned A-query fake DNS path.
- Either implement Trojan ws/grpc or make unsupported transport status more prominent when importing/selecting nodes.
- Add Trojan client certificate/private-key support if subscriptions need it.