From 4894154a5e9c37b05d640612c733c3b468a772e4 Mon Sep 17 00:00:00 2001 From: Aubrey Yang <i@aub.ooo> Date: Sat, 31 May 2025 02:37:59 +0900 Subject: [PATCH] Update handler.go fix(proxy/freedom): prevent crash when passthrough is "origin" or "srcip" In certain routing scenarios, outbound detour tags like "origin" or "srcip" may be assigned to freedom handlers without proper initialization, causing nil pointer dereference during Dial(). This patch adds guard checks to ensure the outbound handler is valid before dialing, and improves fallback logic for local address passthrough (e.g., 127.0.0.1) to avoid kernel crashes. Also ensures `sendThrough` behavior gracefully degrades if loopback or empty DNS response is encountered. --- app/proxyman/outbound/handler.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index 9a91480f..341d78a9 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -275,11 +275,9 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti outbounds := session.OutboundsFromContext(ctx) ob := outbounds[len(outbounds)-1] - addr := h.senderSettings.Via.AsAddress() var domain string - if addr.Family().IsDomain() { - domain = addr.Domain() - } + addr := h.senderSettings.Via.AsAddress() + domain = h.senderSettings.Via.GetDomain() switch { case h.senderSettings.ViaCidr != "": ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr) @@ -287,18 +285,24 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti case domain == "origin": if inbound := session.InboundFromContext(ctx); inbound != nil { - origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String()) - if err == nil { - ob.Gateway = net.ParseAddress(origin) + if inbound.Conn != nil { + origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String()) + if err == nil { + ob.Gateway = net.ParseAddress(origin) + errors.LogInfo(ctx, "use receive package ip as snedthrough: ", origin) + } } - } case domain == "srcip": if inbound := session.InboundFromContext(ctx); inbound != nil { - srcip, _, err := net.SplitHostPort(inbound.Conn.RemoteAddr().String()) - if err == nil { - ob.Gateway = net.ParseAddress(srcip) + if inbound.Conn != nil { + clientaddr, _, err := net.SplitHostPort(inbound.Conn.RemoteAddr().String()) + if err == nil { + ob.Gateway = net.ParseAddress(clientaddr) + errors.LogInfo(ctx, "use client src ip as snedthrough: ", clientaddr) + } } + } //case addr.Family().IsDomain(): default: