Add L3 forwarding support
This commit is contained in:
@@ -5,6 +5,7 @@ package cloudflare
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -13,7 +14,6 @@ import (
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/route/rule"
|
||||
"github.com/sagernet/sing-cloudflared"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
@@ -137,32 +137,44 @@ type icmpRouterHandler struct {
|
||||
tag string
|
||||
}
|
||||
|
||||
func (h *icmpRouterHandler) RouteICMPConnection(ctx context.Context, session tun.DirectRouteSession, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) {
|
||||
var ipVersion uint8
|
||||
if session.Destination.Is4() {
|
||||
ipVersion = 4
|
||||
} else {
|
||||
ipVersion = 6
|
||||
}
|
||||
destination := M.SocksaddrFrom(session.Destination, 0)
|
||||
routeDestination, err := h.router.PreMatch(adapter.InboundContext{
|
||||
Inbound: h.tag,
|
||||
InboundType: C.TypeCloudflared,
|
||||
IPVersion: ipVersion,
|
||||
Network: N.NetworkICMP,
|
||||
Source: M.SocksaddrFrom(session.Source, 0),
|
||||
Destination: destination,
|
||||
OriginDestination: destination,
|
||||
}, routeContext, timeout, false)
|
||||
if err != nil {
|
||||
switch {
|
||||
case rule.IsBypassed(err):
|
||||
err = nil
|
||||
case rule.IsRejected(err):
|
||||
h.logger.Trace("reject ICMP connection from ", session.Source, " to ", session.Destination)
|
||||
default:
|
||||
h.logger.Warn(E.Cause(err, "link ICMP connection from ", session.Source, " to ", session.Destination))
|
||||
func (h *icmpRouterHandler) RouteICMPFlow(source netip.Addr, destination netip.Addr) (tun.Port, error) {
|
||||
result := h.router.PreMatch(adapter.InboundContext{
|
||||
Inbound: h.tag,
|
||||
InboundType: C.TypeCloudflared,
|
||||
Network: N.NetworkICMP,
|
||||
Source: M.SocksaddrFrom(source, 0),
|
||||
Destination: M.SocksaddrFrom(destination, 0),
|
||||
})
|
||||
switch result.Action {
|
||||
case adapter.PreMatchFlow:
|
||||
flowOutbound, isFlowOutbound := result.Outbound.(adapter.FlowOutbound)
|
||||
if !isFlowOutbound {
|
||||
return nil, E.New("outbound is not a flow outbound")
|
||||
}
|
||||
if result.Destination.IsValid() && result.Destination.Addr() != destination {
|
||||
h.logger.Trace("drop ICMP flow from ", source, " to ", destination, ": destination override is not supported from cloudflared")
|
||||
return nil, E.New("destination override is not supported")
|
||||
}
|
||||
inet4Address, inet6Address := flowOutbound.PortAddresses()
|
||||
var portAddress netip.Addr
|
||||
if destination.Is4() {
|
||||
portAddress = inet4Address
|
||||
} else {
|
||||
portAddress = inet6Address
|
||||
}
|
||||
if !portAddress.IsValid() || !portAddress.IsUnspecified() {
|
||||
h.logger.Trace("drop ICMP flow from ", source, " to ", destination, ": forwarding ICMP to outbound/", result.Outbound.Type(), "[", result.Outbound.Tag(), "] is not supported from cloudflared")
|
||||
return nil, E.New("unsupported flow outbound")
|
||||
}
|
||||
h.logger.Debug("link ICMP flow from ", source, " to ", destination, " via outbound/", result.Outbound.Type(), "[", result.Outbound.Tag(), "]")
|
||||
return flowOutbound, nil
|
||||
case adapter.PreMatchReject:
|
||||
h.logger.Trace("reject ICMP flow from ", source, " to ", destination)
|
||||
return nil, E.New("rejected")
|
||||
case adapter.PreMatchDrop:
|
||||
return nil, E.New("dropped")
|
||||
default:
|
||||
h.logger.Trace("drop ICMP flow from ", source, " to ", destination, ": no direct route")
|
||||
return nil, E.New("no direct route")
|
||||
}
|
||||
return routeDestination, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user