mirror of
https://github.com/daeuniverse/dae.git
synced 2025-02-02 04:14:31 +07:00
fix: patch old wan method
This commit is contained in:
parent
9f33ecf809
commit
45701f8559
@ -112,5 +112,6 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
TproxyMark uint32 = 0x80000000
|
||||
TproxyMark uint32 = 0x80000000
|
||||
LoopbackIfIndex = 1
|
||||
)
|
||||
|
@ -7,7 +7,6 @@ package control
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/cilium/ebpf"
|
||||
@ -38,6 +37,7 @@ import (
|
||||
type ControlPlane struct {
|
||||
*ControlPlaneCore
|
||||
deferFuncs []func() error
|
||||
listenIp string
|
||||
|
||||
// TODO: add mutex?
|
||||
outbounds []*outbound.DialerGroup
|
||||
@ -193,16 +193,15 @@ retryLoadBpf:
|
||||
_ = core.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// Bind to links. Binding should be advance of dialerGroups to avoid un-routable old connection.
|
||||
for _, ifname := range lanInterface {
|
||||
if err = core.BindLan(ifname); err != nil {
|
||||
return nil, fmt.Errorf("BindLan: %v: %w", ifname, err)
|
||||
if err = core.bindLan(ifname); err != nil {
|
||||
return nil, fmt.Errorf("bindLan: %v: %w", ifname, err)
|
||||
}
|
||||
}
|
||||
for _, ifname := range wanInterface {
|
||||
if err = core.BindWan(ifname); err != nil {
|
||||
return nil, fmt.Errorf("BindWan: %v: %w", ifname, err)
|
||||
if err = core.bindWan(ifname); err != nil {
|
||||
return nil, fmt.Errorf("bindWan: %v: %w", ifname, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,9 +311,14 @@ retryLoadBpf:
|
||||
}
|
||||
}
|
||||
|
||||
listenIp := "[::1]"
|
||||
if len(wanInterface) > 0 {
|
||||
listenIp = "0.0.0.0"
|
||||
}
|
||||
return &ControlPlane{
|
||||
ControlPlaneCore: core,
|
||||
deferFuncs: nil,
|
||||
listenIp: listenIp,
|
||||
outbounds: outbounds,
|
||||
outboundName2Id: outboundName2Id,
|
||||
SimulatedLpmTries: builder.SimulatedLpmTries,
|
||||
@ -333,12 +337,13 @@ func (c *ControlPlane) ListenAndServe(port uint16) (err error) {
|
||||
return dialer.TproxyControl(c)
|
||||
},
|
||||
}
|
||||
tcpListener, err := listenConfig.Listen(context.TODO(), "tcp", "[::1]:"+strconv.Itoa(int(port)))
|
||||
listenAddr := net.JoinHostPort(c.listenIp, strconv.Itoa(int(port)))
|
||||
tcpListener, err := listenConfig.Listen(context.TODO(), "tcp", listenAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listenTCP: %w", err)
|
||||
}
|
||||
defer tcpListener.Close()
|
||||
packetConn, err := listenConfig.ListenPacket(context.TODO(), "udp", "[::1]:"+strconv.Itoa(int(port)))
|
||||
packetConn, err := listenConfig.ListenPacket(context.TODO(), "udp", listenAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listenUDP: %w", err)
|
||||
}
|
||||
@ -408,21 +413,30 @@ func (c *ControlPlane) ListenAndServe(port uint16) (err error) {
|
||||
break
|
||||
}
|
||||
dst := RetrieveOriginalDest(oob[:oobn])
|
||||
if !dst.IsValid() {
|
||||
c.log.WithFields(logrus.Fields{
|
||||
"source": src.String(),
|
||||
"oob": hex.EncodeToString(oob[:oobn]),
|
||||
}).Warnf("Failed to retrieve original dest")
|
||||
continue
|
||||
var newBuf []byte
|
||||
outboundIndex, err := c.RetrieveOutboundIndex(src, dst, unix.IPPROTO_UDP)
|
||||
if err != nil {
|
||||
// WAN. Old method.
|
||||
addrHdr, dataOffset, err := ParseAddrHdr(buf[:n])
|
||||
if err != nil {
|
||||
c.log.Warnf("No AddrPort presented")
|
||||
continue
|
||||
}
|
||||
newBuf = pool.Get(n - dataOffset)
|
||||
copy(newBuf, buf[dataOffset:n])
|
||||
outboundIndex = consts.OutboundIndex(addrHdr.Outbound)
|
||||
src = netip.AddrPortFrom(dst.Addr(), src.Port())
|
||||
dst = addrHdr.Dest
|
||||
} else {
|
||||
newBuf = pool.Get(n)
|
||||
copy(newBuf, buf[:n])
|
||||
}
|
||||
newBuf := pool.Get(n)
|
||||
copy(newBuf, buf[:n])
|
||||
go func(data []byte, src, dst netip.AddrPort) {
|
||||
if e := c.handlePkt(newBuf, src, dst); e != nil {
|
||||
go func(data []byte, src, dst netip.AddrPort, outboundIndex consts.OutboundIndex) {
|
||||
if e := c.handlePkt(newBuf, src, dst, outboundIndex); e != nil {
|
||||
c.log.Warnln("handlePkt:", e)
|
||||
}
|
||||
pool.Put(newBuf)
|
||||
}(newBuf, src, dst)
|
||||
}(newBuf, src, dst, outboundIndex)
|
||||
}
|
||||
}()
|
||||
<-ctx.Done()
|
||||
|
@ -111,7 +111,7 @@ func getifParamsFromLink(link netlink.Link) (ifParams bpfIfParams, err error) {
|
||||
return ifParams, nil
|
||||
}
|
||||
|
||||
func (c *ControlPlaneCore) BindLan(ifname string) error {
|
||||
func (c *ControlPlaneCore) bindLan(ifname string) error {
|
||||
c.log.Infof("Bind to LAN: %v", ifname)
|
||||
link, err := netlink.LinkByName(ifname)
|
||||
if err != nil {
|
||||
@ -123,7 +123,7 @@ func (c *ControlPlaneCore) BindLan(ifname string) error {
|
||||
ip rule add fwmark 0x80000000/0x80000000 table 2023
|
||||
ip route add local default dev lo table 2023
|
||||
ip -6 rule add fwmark 0x80000000/0x80000000 table 2023
|
||||
ip -6 route add local ::/0 dev lo table 2023
|
||||
ip -6 route add local default dev lo table 2023
|
||||
`).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("%w: %v", err, string(bytes.TrimSpace(output)))
|
||||
}
|
||||
@ -132,7 +132,7 @@ func (c *ControlPlaneCore) BindLan(ifname string) error {
|
||||
ip rule del fwmark 0x80000000/0x80000000 table 2023
|
||||
ip route del local default dev lo table 2023
|
||||
ip -6 rule del fwmark 0x80000000/0x80000000 table 2023
|
||||
ip -6 route del local ::/0 dev lo table 2023
|
||||
ip -6 route del local default dev lo table 2023
|
||||
`).Run()
|
||||
})
|
||||
/// Insert an elem into IfindexParamsMap.
|
||||
@ -208,12 +208,15 @@ func (c *ControlPlaneCore) BindLan(ifname string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ControlPlaneCore) BindWan(ifname string) error {
|
||||
func (c *ControlPlaneCore) bindWan(ifname string) error {
|
||||
c.log.Infof("Bind to WAN: %v", ifname)
|
||||
link, err := netlink.LinkByName(ifname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if link.Attrs().Index == consts.LoopbackIfIndex {
|
||||
return fmt.Errorf("cannot bind to loopback interface")
|
||||
}
|
||||
/// Insert an elem into IfindexParamsMap.
|
||||
ifParams, err := getifParamsFromLink(link)
|
||||
if err != nil {
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
// #define __DEBUG_ROUTING
|
||||
// #define __PRINT_ROUTING_RESULT
|
||||
// #define __PRINT_SETUP_PROCESS_CONNNECTION
|
||||
// #define __REMOVE_BPF_PRINTK
|
||||
|
||||
#ifdef __REMOVE_BPF_PRINTK
|
||||
@ -130,6 +131,8 @@ struct {
|
||||
__type(key, struct tuples);
|
||||
__type(value, __u32); // outbound
|
||||
__uint(max_entries, MAX_DST_MAPPING_NUM);
|
||||
/// NOTICE: It MUST be pinned.
|
||||
__uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
} routing_tuples_map SEC(".maps");
|
||||
|
||||
// Params:
|
||||
@ -1197,6 +1200,7 @@ int tproxy_lan_ingress(struct __sk_buff *skb) {
|
||||
ip -6 rule del fwmark 0x80000000/0x80000000 table 2023
|
||||
ip -6 route del local ::/0 dev lo table 2023
|
||||
*/
|
||||
// Socket lookup and assign skb to existing socket connection.
|
||||
struct bpf_sock_tuple tuple = {0};
|
||||
__u32 tuple_size;
|
||||
struct bpf_sock *sk;
|
||||
@ -1204,7 +1208,6 @@ int tproxy_lan_ingress(struct __sk_buff *skb) {
|
||||
__u32 flag[6] = {0};
|
||||
void *l4hdr;
|
||||
|
||||
// Socket lookup and assign skb to existing socket connection.
|
||||
if (ipversion == 4) {
|
||||
tuple.ipv4.daddr = tuples.dst.ip[3];
|
||||
tuple.ipv4.saddr = tuples.src.ip[3];
|
||||
@ -1963,7 +1966,9 @@ static int __always_inline update_map_elem_by_cookie(const __u64 cookie) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __PRINT_SETUP_PROCESS_CONNNECTION
|
||||
bpf_printk("setup_mapping: %llu -> %s (%d)", cookie, val.pname, val.pid);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ func generate(output string) error {
|
||||
Ebpf: structField.Tag.Get("ebpf"),
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("unexpected prefix, should be TproxyWan or TproxyLan: %v", structField.Name)
|
||||
return fmt.Errorf("unexpected program name which should begin with TproxyWan or TproxyLan, but get: %v", structField.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,9 +9,12 @@ import (
|
||||
"fmt"
|
||||
"github.com/mzz2017/softwind/pkg/zeroalloc/io"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
internal "github.com/v2rayA/dae/pkg/ebpf_internal"
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -20,12 +23,27 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
|
||||
defer lConn.Close()
|
||||
src := lConn.RemoteAddr().(*net.TCPAddr).AddrPort()
|
||||
dst := lConn.LocalAddr().(*net.TCPAddr).AddrPort()
|
||||
outboundIndex, _, err := c.RetrieveOutboundIndex(src, dst, unix.IPPROTO_TCP)
|
||||
outboundIndex, err := c.RetrieveOutboundIndex(src, dst, unix.IPPROTO_TCP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("RetrieveOutboundIndex: %w", err)
|
||||
// WAN. Old method.
|
||||
var value bpfIpPortOutbound
|
||||
ip6 := src.Addr().As16()
|
||||
if e := c.bpf.TcpDstMap.Lookup(bpfIpPort{
|
||||
Ip: common.Ipv6ByteSliceToUint32Array(ip6[:]),
|
||||
Port: internal.Htons(src.Port()),
|
||||
}, &value); e != nil {
|
||||
return fmt.Errorf("failed to retrieve target info %v: %v, %v", src.String(), err, e)
|
||||
}
|
||||
outboundIndex = consts.OutboundIndex(value.Outbound)
|
||||
|
||||
dstAddr, ok := netip.AddrFromSlice(common.Ipv6Uint32ArrayToByteSlice(value.Ip))
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to parse dest ip: %v", value.Ip)
|
||||
}
|
||||
dst = netip.AddrPortFrom(dstAddr, internal.Htons(value.Port))
|
||||
}
|
||||
|
||||
switch consts.OutboundIndex(outboundIndex) {
|
||||
switch outboundIndex {
|
||||
case consts.OutboundDirect:
|
||||
case consts.OutboundControlPlaneDirect:
|
||||
outboundIndex = consts.OutboundDirect
|
||||
|
@ -16,11 +16,11 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (c *ControlPlaneCore) RetrieveOutboundIndex(src, dst netip.AddrPort, l4proto uint8) (outboundIndex consts.OutboundIndex, tuples *bpfTuples, err error) {
|
||||
func (c *ControlPlaneCore) RetrieveOutboundIndex(src, dst netip.AddrPort, l4proto uint8) (outboundIndex consts.OutboundIndex, err error) {
|
||||
srcIp6 := src.Addr().As16()
|
||||
dstIp6 := dst.Addr().As16()
|
||||
|
||||
tuples = &bpfTuples{
|
||||
tuples := &bpfTuples{
|
||||
Src: bpfIpPort{
|
||||
Ip: common.Ipv6ByteSliceToUint32Array(srcIp6[:]),
|
||||
Port: internal.Htons(src.Port()),
|
||||
@ -34,12 +34,12 @@ func (c *ControlPlaneCore) RetrieveOutboundIndex(src, dst netip.AddrPort, l4prot
|
||||
|
||||
var _outboundIndex uint32
|
||||
if err := c.bpf.RoutingTuplesMap.Lookup(tuples, &_outboundIndex); err != nil {
|
||||
return 0, nil, fmt.Errorf("reading map: key [%v, %v, %v]: %w", src.String(), l4proto, dst.String(), err)
|
||||
return 0, fmt.Errorf("reading map: key [%v, %v, %v]: %w", src.String(), l4proto, dst.String(), err)
|
||||
}
|
||||
if _outboundIndex > uint32(consts.OutboundLogicalMax) {
|
||||
return 0, nil, fmt.Errorf("bad outbound index")
|
||||
return 0, fmt.Errorf("bad outbound index")
|
||||
}
|
||||
return consts.OutboundIndex(_outboundIndex), tuples, nil
|
||||
return consts.OutboundIndex(_outboundIndex), nil
|
||||
}
|
||||
|
||||
func RetrieveOriginalDest(oob []byte) netip.AddrPort {
|
||||
@ -55,7 +55,7 @@ func RetrieveOriginalDest(oob []byte) netip.AddrPort {
|
||||
} else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == unix.IPV6_RECVORIGDSTADDR {
|
||||
ip := msg.Data[8:24]
|
||||
port := binary.BigEndian.Uint16(msg.Data[2:4])
|
||||
return netip.AddrPortFrom(netip.AddrFrom4(*(*[4]byte)(ip)), port)
|
||||
return netip.AddrPortFrom(netip.AddrFrom16(*(*[16]byte)(ip)), port)
|
||||
}
|
||||
}
|
||||
return netip.AddrPort{}
|
||||
|
@ -14,7 +14,6 @@ import (
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
@ -123,11 +122,7 @@ func (c *ControlPlane) RelayToUDP(to netip.AddrPort, isDNS bool, dummyFrom *neti
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ControlPlane) handlePkt(data []byte, src, dst netip.AddrPort) (err error) {
|
||||
outboundIndex, _, err := c.RetrieveOutboundIndex(src, dst, unix.IPPROTO_UDP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("RetrieveOutboundIndex: %w", err)
|
||||
}
|
||||
func (c *ControlPlane) handlePkt(data []byte, src, dst netip.AddrPort, outboundIndex consts.OutboundIndex) (err error) {
|
||||
switch outboundIndex {
|
||||
case consts.OutboundDirect:
|
||||
case consts.OutboundControlPlaneDirect:
|
||||
|
@ -110,6 +110,13 @@ func bindAddr(fd uintptr, addrPort netip.AddrPort) error {
|
||||
a6 := &syscall.SockaddrInet6{
|
||||
Port: int(addrPort.Port()),
|
||||
}
|
||||
zone := addrPort.Addr().Zone()
|
||||
if zone != "" {
|
||||
//if link, e := netlink.LinkByName(zone); e == nil {
|
||||
// a6.ZoneId = uint32(link.Attrs().Index)
|
||||
//}
|
||||
return fmt.Errorf("unsupported ipv6 zone")
|
||||
}
|
||||
a6.Addr = addr.As16()
|
||||
sockAddr = a6
|
||||
default:
|
||||
|
12
insert.sh
12
insert.sh
@ -3,7 +3,7 @@ lan=docker0
|
||||
wan=wlp5s0
|
||||
|
||||
sudo tc qdisc add dev $lan clsact > /dev/null 2>&1
|
||||
# sudo tc qdisc add dev $wan clsact > /dev/null 2>&1
|
||||
sudo tc qdisc add dev $wan clsact > /dev/null 2>&1
|
||||
|
||||
set -ex
|
||||
|
||||
@ -13,11 +13,11 @@ sudo rm -rf /sys/fs/bpf/tc/globals/*
|
||||
clang -O2 -g -Wall -Werror -c component/control/kern/tproxy.c -target bpf -D__TARGET_ARCH_x86 -o foo.o
|
||||
sudo tc filter del dev $lan ingress
|
||||
sudo tc filter del dev $lan egress
|
||||
# sudo tc filter del dev $wan ingress
|
||||
# sudo tc filter del dev $wan egress
|
||||
sudo tc filter del dev $wan ingress
|
||||
sudo tc filter del dev $wan egress
|
||||
|
||||
sudo tc filter add dev $lan ingress bpf direct-action obj foo.o sec tc/ingress
|
||||
# sudo tc filter add dev $lan egress bpf direct-action obj foo.o sec tc/egress
|
||||
# sudo tc filter add dev $wan ingress bpf direct-action obj foo.o sec tc/wan_ingress
|
||||
# sudo tc filter add dev $wan egress bpf direct-action obj foo.o sec tc/wan_egress
|
||||
sudo tc filter add dev $wan ingress bpf direct-action obj foo.o sec tc/wan_ingress
|
||||
sudo tc filter add dev $wan egress bpf direct-action obj foo.o sec tc/wan_egress
|
||||
|
||||
exit 0
|
Loading…
Reference in New Issue
Block a user