Skip to content

Commit e3ee482

Browse files
committed
tcp,udp: attempt port forward on remote proxies
1 parent 0c015a4 commit e3ee482

5 files changed

Lines changed: 44 additions & 28 deletions

File tree

intra/dnsx/transport.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ const (
6666
// preferred forwarding network, if any
6767
// ipn.Base is treated as a no-proxy
6868
NetBaseProxy = x.Base
69+
NetAutoProxy = x.Auto
6970
NetNoProxy = x.Block
7071
NetExitProxy = x.Exit
7172

@@ -1243,6 +1244,11 @@ func IsLocalProxy(pid string) bool {
12431244
pid == NetNoProxy
12441245
}
12451246

1247+
// return true ipn.Auto
1248+
func IsAutoProxy(pid string) bool {
1249+
return pid == NetAutoProxy
1250+
}
1251+
12461252
// RegisterAddrs registers IP ports with all dialers for a given hostname.
12471253
// If id is dnsx.Bootstrap, the hostname is "protected" from re-resolutions.
12481254
// hostname is a domain name, and as a special case, can be protect.UidSelf or protect.UidSystem.

intra/ipn/proxies.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1425,14 +1425,18 @@ func local(id string) bool {
14251425
return id == Base || id == Block || id == Exit || id == Rpn64 || id == Ingress
14261426
}
14271427

1428+
func automatic(id string) bool {
1429+
return id == Auto
1430+
}
1431+
14281432
func noop(typ string) bool {
14291433
return typ == NOOP
14301434
}
14311435

14321436
// TODO: check for hops on "noop" transports; if those
14331437
// are NOT hoppping, then those are NOT remote, either
14341438
func Remote(id string) bool {
1435-
return !local(id)
1439+
return !local(id) || !automatic(id)
14361440
}
14371441

14381442
func hopping(r x.Router) bool {

intra/tcp.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,14 +377,16 @@ func (h *tcpHandler) handle(px ipn.Proxy, gconn *netstack.GTCPConn, src, target
377377
}
378378

379379
var bindAddr netip.AddrPort
380+
pid := pidstr(px)
380381
eim := settings.EndpointIndependentMapping.Load()
381382
portfwd := settings.PortForward.Load()
383+
canportfwd := portfwd && ipn.Remote(pid)
382384

383-
if portfwd { // port forwarding overriden by eim
384-
bindAddr = makeAnyAddrPort(src)
385-
}
386385
if eim { // bindAddr may be invalid
387-
bindAddr = h.natLookup(pidstr(px), src, target)
386+
bindAddr = h.natLookup(pid, src, target)
387+
}
388+
if !bindAddr.IsValid() && canportfwd { // port forwarding overriden by eim
389+
bindAddr = makeAnyAddrPort(src)
388390
}
389391

390392
var pc protect.Conn
@@ -393,8 +395,8 @@ func (h *tcpHandler) handle(px ipn.Proxy, gconn *netstack.GTCPConn, src, target
393395
start := time.Now()
394396

395397
if settings.Debug {
396-
log.VV("tcp: %s dial %s: attempt: %s [%s [%s]] => %s for %s",
397-
smm.ID, pidstr(px), src, gconn.LocalAddr(), bindAddr, targetstr, smm.UID)
398+
log.VV("tcp: %s dial %s: attempt(eim? %t / fwd? %t / canfwd? %t): %s [%s [%s]] => %s for %s",
399+
smm.ID, pid, eim, portfwd, canportfwd, src, gconn.LocalAddr(), bindAddr, targetstr, smm.UID)
398400
}
399401

400402
dialbindOK := false
@@ -405,7 +407,7 @@ func (h *tcpHandler) handle(px ipn.Proxy, gconn *netstack.GTCPConn, src, target
405407
pc, err = px.Dialer().DialBind("tcp", bindAddr.String(), targetstr)
406408
dialbindOK = err == nil
407409
logwif(!dialbindOK)("tcp: %s dialbind ok? %t (%s [%s] => %s via %s); err? %v",
408-
smm.ID, dialbindOK, src, bindAddr, targetstr, pidstr(px), err)
410+
smm.ID, dialbindOK, src, bindAddr, targetstr, pid, err)
409411
}
410412
if !dialbindOK {
411413
pc, err = px.Dialer().Dial("tcp", targetstr)

intra/udp.go

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ func (h *udpHandler) Connect(gconn *netstack.GUDPConn, src, target netip.AddrPor
272272
var errs error
273273
var selectedTarget netip.AddrPort
274274

275+
portfwd := settings.PortForward.Load()
276+
canportfwd := portfwd
275277
if mux {
276278
if muxpid := h.mux.pid(src); len(muxpid) > 0 && containsPid(pids, muxpid) {
277279
if settings.Debug {
@@ -283,8 +285,8 @@ func (h *udpHandler) Connect(gconn *netstack.GUDPConn, src, target netip.AddrPor
283285
}
284286

285287
if settings.Debug {
286-
log.VV("udp: connect: %s [%s] proxying %s => %s [%v]; pids: %s, mux? %t",
287-
cid, uid, src, target, actualTargets, pids, mux)
288+
log.VV("udp: connect: %s [%s] proxying %s => %s [%v]; pids: %s, mux? %t / fwd? %t",
289+
cid, uid, src, target, actualTargets, pids, mux, canportfwd)
288290
}
289291

290292
// note: fake-dns-ips shouldn't be un-nated / un-alg'd
@@ -301,20 +303,22 @@ func (h *udpHandler) Connect(gconn *netstack.GUDPConn, src, target netip.AddrPor
301303
selectedTarget = dstipp
302304

303305
if err != nil || px == nil {
304-
log.W("udp: connect: #%d: %s [%s] failed to get proxy from %s: %v", i, cid, uid, pidstr(px), err)
306+
log.W("udp: connect: #%d: %s [%s] failed to get proxy from %s: %v", i, cid, uid, pxid, err)
305307
errs = err // disconnect if loop terminates
306308
continue
307309
}
308310

311+
canportfwd = portfwd && ipn.Remote(pxid)
312+
309313
if mux { // mux is not supported by all proxies (few like Exit, Base, WG support it)
310-
pc, err = h.mux.associate(cid, pxid, uid, src, selectedTarget, px.Dialer().Announce, vendor(dmx))
314+
pc, err = h.mux.associate(cid, pxid, uid, src, selectedTarget, px.Dialer().Announce, vendor(dmx), canportfwd)
311315
} else {
312316
if settings.Debug {
313-
log.VV("udp: connect: #%d: attempt: %s [%s] proxy(%s) to dst(%s); mux? %t",
314-
i, cid, uid, pxid, selectedTarget, mux)
317+
log.VV("udp: connect: #%d: attempt: %s [%s] proxy(%s) to dst(%s); mux? %t / fwd? %t",
318+
i, cid, uid, pxid, selectedTarget, mux, canportfwd)
315319
}
316320

317-
if settings.PortForward.Load() {
321+
if canportfwd {
318322
boundSrc := makeAnyAddrPort(src)
319323
pc, err = px.Dialer().DialBind("udp", boundSrc.String(), selectedTarget.String())
320324
} else {
@@ -329,8 +333,8 @@ func (h *udpHandler) Connect(gconn *netstack.GUDPConn, src, target netip.AddrPor
329333
errs = err // store just the last err; complicates logging
330334
end := time.Since(smm.start)
331335
smm.Rtt = time.Since(rttstart).Milliseconds()
332-
log.W("udp: connect: #%d: %s [%s] failed; mux? %t, addr(%s) / fallback? %t; (rtt:%dms, dur:%s) w err(%v)",
333-
i, cid, uid, mux, dstipp, fallingback, smm.Rtt, core.FmtPeriod(end), err)
336+
log.W("udp: connect: #%d: %s [%s] failed; mux? %t / fwd? %t, addr(%s) / fallback? %t; (rtt:%dms, dur:%s) w err(%v)",
337+
i, cid, uid, mux, canportfwd, dstipp, fallingback, smm.Rtt, core.FmtPeriod(end), err)
334338
if end > retryTimeout {
335339
break
336340
}
@@ -343,7 +347,8 @@ func (h *udpHandler) Connect(gconn *netstack.GUDPConn, src, target netip.AddrPor
343347
}
344348

345349
if !selectedTarget.IsValid() {
346-
log.E("udp: connect: %s [%s] no target addr for %s from %v", cid, uid, target, actualTargets)
350+
log.E("udp: connect: %s [%s] no target addr for %s from %v",
351+
cid, uid, target, actualTargets)
347352
return nil, smm, errUdpNoTarget
348353
}
349354

@@ -354,8 +359,8 @@ func (h *udpHandler) Connect(gconn *netstack.GUDPConn, src, target netip.AddrPor
354359
if errs != nil {
355360
return nil, smm, errs // disconnect
356361
} else if px == nil || pc == nil || core.IsNil(pc) {
357-
log.W("udp: connect: %s [%s] no proxy/egress-conn (mux? %t) for addr(%s/%s)",
358-
cid, uid, mux, target, selectedTarget)
362+
log.W("udp: connect: %s [%s] no proxy/egress-conn (mux? %t / fwd? %t) for addr(%s/%s)",
363+
cid, uid, mux, canportfwd, target, selectedTarget)
359364
return nil, smm, errUdpSetupConn // disconnect
360365
}
361366

@@ -370,12 +375,12 @@ func (h *udpHandler) Connect(gconn *netstack.GUDPConn, src, target netip.AddrPor
370375
default:
371376
clos(pc)
372377
log.E("udp: connect: %s [%s] proxy(%s) does not impl core.UDPConn(%s/%s); mux? %t",
373-
cid, uid, pxid, target, selectedTarget, mux, uid)
378+
cid, uid, pxid, target, selectedTarget, mux, canportfwd, uid)
374379
return nil, smm, errUdpSetupConn // disconnect
375380
}
376381

377-
log.I("udp: connect: %s [%s] (proxy? %s@%s) %v => %s/%s; fallback? %t / mux? %t",
378-
cid, uid, pxid, px.GetAddr(), laddr, target, selectedTarget, fallingback, mux)
382+
log.I("udp: connect: %s [%s] (proxy? %s@%s) %v => %s/%s; fallback? %t / mux? %t / fwd? %t",
383+
cid, uid, pxid, px.GetAddr(), laddr, target, selectedTarget, fallingback, mux, canportfwd)
379384

380385
return pc, smm, nil // connect
381386
}

intra/udpmux.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818

1919
"github.com/celzero/firestack/intra/core"
2020
"github.com/celzero/firestack/intra/dialers"
21-
"github.com/celzero/firestack/intra/ipn"
2221
"github.com/celzero/firestack/intra/log"
2322
"github.com/celzero/firestack/intra/settings"
2423
)
@@ -600,7 +599,7 @@ func (e *muxTable) pid(src netip.AddrPort) string {
600599
return ""
601600
}
602601

603-
func (e *muxTable) associate(cid, pid, uid string, src, dst netip.AddrPort, mk assocFn, v vendor) (_ net.Conn, err error) {
602+
func (e *muxTable) associate(cid, pid, uid string, src, dst netip.AddrPort, mk assocFn, v vendor, portfwd bool) (_ net.Conn, err error) {
604603
e.Lock() // lock
605604

606605
pxm := e.t[pid]
@@ -621,7 +620,7 @@ func (e *muxTable) associate(cid, pid, uid string, src, dst netip.AddrPort, mk a
621620
anyaddr = anyaddr4
622621
}
623622
anyaddrport := netip.AddrPortFrom(anyaddr, anyport)
624-
if settings.PortForward.Load() || ipn.Remote(pid) {
623+
if portfwd {
625624
anyaddrport = netip.AddrPortFrom(anyaddr, src.Port())
626625
}
627626

@@ -637,8 +636,8 @@ func (e *muxTable) associate(cid, pid, uid string, src, dst netip.AddrPort, mk a
637636
e.dissociate(cid, pid, src)
638637
})
639638
pxm[src] = mxr
640-
log.I("udp: mux: %s new assoc for %s %s via %s",
641-
cid, pid, src, anyaddrport)
639+
log.I("udp: mux: %s new assoc for %s %s via %s; fwd? %t",
640+
cid, pid, src, anyaddrport, portfwd)
642641
}
643642

644643
if mxr.pid != pid {

0 commit comments

Comments
 (0)