feat: add more trace info (pid, pname, mac)

This commit is contained in:
mzz2017
2023-02-21 16:10:44 +08:00
parent 474342c8f0
commit 384b4131a3
8 changed files with 143 additions and 110 deletions

View File

@ -15,8 +15,6 @@ const (
AppName = "dae" AppName = "dae"
BpfPinRoot = "/sys/fs/bpf" BpfPinRoot = "/sys/fs/bpf"
AddrHdrSize = 24
TaskCommLen = 16 TaskCommLen = 16
) )

View File

@ -20,6 +20,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unsafe"
) )
var ( var (
@ -393,3 +394,16 @@ func AddrToDnsType(addr netip.Addr) dnsmessage.Type {
return dnsmessage.TypeAAAA return dnsmessage.TypeAAAA
} }
} }
// Htons converts the unsigned short integer hostshort from host byte order to network byte order.
func Htons(i uint16) uint16 {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, i)
return *(*uint16)(unsafe.Pointer(&b[0]))
}
// Ntohs converts the unsigned short integer hostshort from host byte order to network byte order.
func Ntohs(i uint16) uint16 {
bytes := *(*[2]byte)(unsafe.Pointer(&i))
return binary.BigEndian.Uint16(bytes[:])
}

View File

@ -347,7 +347,7 @@ func (c *ControlPlane) finishInitDnsUpstreamResolve(raw common.UrlOrEmpty, dnsUp
Ip6: common.Ipv6ByteSliceToUint32Array(ip6[:]), Ip6: common.Ipv6ByteSliceToUint32Array(ip6[:]),
HasIp4: dnsUpstream.Ip4.IsValid(), HasIp4: dnsUpstream.Ip4.IsValid(),
HasIp6: dnsUpstream.Ip6.IsValid(), HasIp6: dnsUpstream.Ip6.IsValid(),
Port: internal.Htons(dnsUpstream.Port), Port: common.Htons(dnsUpstream.Port),
}, ebpf.UpdateAny); err != nil { }, ebpf.UpdateAny); err != nil {
return err return err
} }
@ -485,7 +485,7 @@ func (c *ControlPlane) ListenAndServe(port uint16) (err error) {
return err return err
} }
// Port. // Port.
if err := c.core.bpf.ParamMap.Update(consts.BigEndianTproxyPortKey, uint32(internal.Htons(port)), ebpf.UpdateAny); err != nil { if err := c.core.bpf.ParamMap.Update(consts.BigEndianTproxyPortKey, uint32(common.Htons(port)), ebpf.UpdateAny); err != nil {
return err return err
} }
@ -535,16 +535,16 @@ func (c *ControlPlane) ListenAndServe(port uint16) (err error) {
// WAN. Old method. // WAN. Old method.
addrHdr, dataOffset, err := ParseAddrHdr(data) addrHdr, dataOffset, err := ParseAddrHdr(data)
if err != nil { if err != nil {
c.log.Warnf("No AddrPort presented") c.log.Warnf("No AddrPort presented: %v", err)
return return
} }
copy(data, data[dataOffset:]) copy(data, data[dataOffset:])
routingResult = &bpfRoutingResult{ routingResult = &addrHdr.RoutingResult
Mark: addrHdr.Mark, __ip := common.Ipv6Uint32ArrayToByteSlice(addrHdr.Ip)
Outbound: addrHdr.Outbound, _ip, _ := netip.AddrFromSlice(__ip)
} // Comment it because them SHOULD equal.
src = netip.AddrPortFrom(addrHdr.Dest.Addr(), src.Port()) //src = netip.AddrPortFrom(_ip, src.Port())
realDst = addrHdr.Dest realDst = netip.AddrPortFrom(_ip, addrHdr.Port)
} else { } else {
realDst = pktDst realDst = pktDst
} }

View File

@ -127,12 +127,18 @@ struct ip_port {
__be16 port; __be16 port;
}; };
struct ip_port_outbound { struct routing_result {
__u32 mark;
__u8 mac[6];
__u8 outbound;
__u8 pname[TASK_COMM_LEN];
__u32 pid;
};
struct dst_routing_result {
__be32 ip[4]; __be32 ip[4];
__be16 port; __be16 port;
__u8 outbound; struct routing_result routing_result;
__u8 unused;
__u32 mark;
}; };
struct tuples { struct tuples {
@ -150,18 +156,13 @@ struct {
// (source ip, source port, tcp) is // (source ip, source port, tcp) is
// enough for identifier. And UDP client // enough for identifier. And UDP client
// side does not care it (full-cone). // side does not care it (full-cone).
__type(value, struct ip_port_outbound); // Original target. __type(value, struct dst_routing_result); // Original target.
__uint(max_entries, MAX_DST_MAPPING_NUM); __uint(max_entries, MAX_DST_MAPPING_NUM);
/// NOTICE: It MUST be pinned. /// NOTICE: It MUST be pinned.
__uint(pinning, LIBBPF_PIN_BY_NAME); __uint(pinning, LIBBPF_PIN_BY_NAME);
} tcp_dst_map } tcp_dst_map
SEC(".maps"); // This map is only for old method (redirect mode in WAN). SEC(".maps"); // This map is only for old method (redirect mode in WAN).
struct routing_result {
__u32 mark;
__u8 outbound;
};
struct { struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, struct tuples); __type(key, struct tuples);
@ -1180,8 +1181,8 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
} }
static bool __always_inline is_not_to_lan(void *_ori_src) { static bool __always_inline is_not_to_lan(void *_ori_src) {
struct ip_port_outbound *ori_src = _ori_src; struct dst_routing_result *ori_src = _ori_src;
return ori_src->outbound == IS_WAN; return ori_src->routing_result.outbound == IS_WAN;
} }
// SNAT for UDP packet. // SNAT for UDP packet.
@ -1218,7 +1219,7 @@ int tproxy_lan_egress(struct __sk_buff *skb) {
return TC_ACT_PIPE; return TC_ACT_PIPE;
} }
struct ip_port_outbound ori_src; struct dst_routing_result ori_src;
if ((ret = decap_after_udp_hdr(skb, ipversion, ihl, if ((ret = decap_after_udp_hdr(skb, ipversion, ihl,
ipversion == 4 ? iph.tot_len : 0, &ori_src, ipversion == 4 ? iph.tot_len : 0, &ori_src,
sizeof(ori_src), is_not_to_lan, true))) { sizeof(ori_src), is_not_to_lan, true))) {
@ -1347,6 +1348,10 @@ new_connection:
struct routing_result routing_result = {0}; struct routing_result routing_result = {0};
routing_result.outbound = ret; routing_result.outbound = ret;
routing_result.mark = ret >> 8; routing_result.mark = ret >> 8;
__builtin_memcpy(routing_result.mac, ethh.h_source,
sizeof(routing_result.mac));
// No pid pname info in LAN.
// Save routing result. // Save routing result.
if ((ret = bpf_map_update_elem(&routing_tuples_map, &tuples, &routing_result, if ((ret = bpf_map_update_elem(&routing_tuples_map, &tuples, &routing_result,
BPF_ANY))) { BPF_ANY))) {
@ -1597,6 +1602,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
key_src.port = tcph.source; key_src.port = tcph.source;
__u8 outbound; __u8 outbound;
__u32 mark; __u32 mark;
struct pid_pname *pid_pname = NULL;
if (unlikely(tcp_state_syn)) { if (unlikely(tcp_state_syn)) {
// New TCP connection. // New TCP connection.
// bpf_printk("[%X]New Connection", bpf_ntohl(tcph.seq)); // bpf_printk("[%X]New Connection", bpf_ntohl(tcph.seq));
@ -1606,7 +1612,6 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
} else { } else {
flag[1] = IpVersionType_4; flag[1] = IpVersionType_4;
} }
struct pid_pname *pid_pname;
if (pid_is_control_plane(skb, &pid_pname)) { if (pid_is_control_plane(skb, &pid_pname)) {
// From control plane. Direct. // From control plane. Direct.
return TC_ACT_OK; return TC_ACT_OK;
@ -1641,14 +1646,14 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
} else { } else {
// bpf_printk("[%X]Old Connection", bpf_ntohl(tcph.seq)); // bpf_printk("[%X]Old Connection", bpf_ntohl(tcph.seq));
// The TCP connection exists. // The TCP connection exists.
struct ip_port_outbound *dst = struct dst_routing_result *dst =
bpf_map_lookup_elem(&tcp_dst_map, &key_src); bpf_map_lookup_elem(&tcp_dst_map, &key_src);
if (!dst) { if (!dst) {
// Do not impact previous connections. // Do not impact previous connections.
return TC_ACT_OK; return TC_ACT_OK;
} }
outbound = dst->outbound; outbound = dst->routing_result.outbound;
mark = dst->mark; mark = dst->routing_result.mark;
} }
if ((outbound == OUTBOUND_DIRECT || outbound == OUTBOUND_MUST_DIRECT) && if ((outbound == OUTBOUND_DIRECT || outbound == OUTBOUND_MUST_DIRECT) &&
@ -1675,15 +1680,22 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
} }
if (unlikely(tcp_state_syn)) { if (unlikely(tcp_state_syn)) {
struct ip_port_outbound value_dst; struct dst_routing_result routing_info;
__builtin_memset(&value_dst, 0, sizeof(value_dst)); __builtin_memset(&routing_info, 0, sizeof(routing_info));
__builtin_memcpy(value_dst.ip, &tuples.dip, IPV6_BYTE_LENGTH); __builtin_memcpy(routing_info.ip, &tuples.dip, IPV6_BYTE_LENGTH);
value_dst.port = tcph.dest; routing_info.port = tcph.dest;
value_dst.outbound = outbound; routing_info.routing_result.outbound = outbound;
value_dst.mark = mark; routing_info.routing_result.mark = mark;
__builtin_memcpy(routing_info.routing_result.mac, ethh.h_source,
sizeof(ethh.h_source));
if (pid_pname) {
__builtin_memcpy(routing_info.routing_result.pname, pid_pname->pname,
TASK_COMM_LEN);
routing_info.routing_result.pid = pid_pname->pid;
}
// bpf_printk("UPDATE: %pI6:%u", key_src.ip.u6_addr32, // bpf_printk("UPDATE: %pI6:%u", key_src.ip.u6_addr32,
// bpf_ntohs(key_src.port)); // bpf_ntohs(key_src.port));
bpf_map_update_elem(&tcp_dst_map, &key_src, &value_dst, BPF_ANY); bpf_map_update_elem(&tcp_dst_map, &key_src, &routing_info, BPF_ANY);
} }
// Write mac. // Write mac.
@ -1699,11 +1711,6 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
}; };
} else if (l4proto == IPPROTO_UDP) { } else if (l4proto == IPPROTO_UDP) {
// Backup for further use.
struct ip_port_outbound new_hdr;
__builtin_memset(&new_hdr, 0, sizeof(new_hdr));
__builtin_memcpy(new_hdr.ip, &tuples.dip, IPV6_BYTE_LENGTH);
new_hdr.port = udph.dest;
// Routing. It decides if we redirect traffic to control plane. // Routing. It decides if we redirect traffic to control plane.
__u32 flag[6] = {L4ProtoType_UDP}; __u32 flag[6] = {L4ProtoType_UDP};
@ -1732,8 +1739,20 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
bpf_printk("shot routing: %d", ret); bpf_printk("shot routing: %d", ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
new_hdr.outbound = ret; // Construct new hdr to encap.
new_hdr.mark = ret >> 8; struct dst_routing_result new_hdr;
__builtin_memset(&new_hdr, 0, sizeof(new_hdr));
__builtin_memcpy(new_hdr.ip, &tuples.dip, IPV6_BYTE_LENGTH);
new_hdr.port = udph.dest;
new_hdr.routing_result.outbound = ret;
new_hdr.routing_result.mark = ret >> 8;
__builtin_memcpy(new_hdr.routing_result.mac, ethh.h_source,
sizeof(ethh.h_source));
if (pid_pname) {
__builtin_memcpy(new_hdr.routing_result.pname, pid_pname->pname,
TASK_COMM_LEN);
new_hdr.routing_result.pid = pid_pname->pid;
}
#if defined(__DEBUG_ROUTING) || defined(__PRINT_ROUTING_RESULT) #if defined(__DEBUG_ROUTING) || defined(__PRINT_ROUTING_RESULT)
__u32 pid = pid_pname ? pid_pname->pid : 0; __u32 pid = pid_pname ? pid_pname->pid : 0;
bpf_printk("udp(wan): from %pI6:%u [PID %u]", tuples.sip.u6_addr32, bpf_printk("udp(wan): from %pI6:%u [PID %u]", tuples.sip.u6_addr32,
@ -1742,13 +1761,13 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
tuples.dip.u6_addr32, bpf_ntohs(tuples.dport)); tuples.dip.u6_addr32, bpf_ntohs(tuples.dport));
#endif #endif
if ((new_hdr.outbound == OUTBOUND_DIRECT || if ((new_hdr.routing_result.outbound == OUTBOUND_DIRECT ||
new_hdr.outbound == OUTBOUND_MUST_DIRECT) && new_hdr.routing_result.outbound == OUTBOUND_MUST_DIRECT) &&
new_hdr.mark == 0 // If mark is not zero, we should re-route it, so we new_hdr.routing_result.mark == 0 // If mark is not zero, we should re-route it, so we
// send it to control plane in WAN. // send it to control plane in WAN.
) { ) {
return TC_ACT_OK; return TC_ACT_OK;
} else if (unlikely(new_hdr.outbound == OUTBOUND_BLOCK)) { } else if (unlikely(new_hdr.routing_result.outbound == OUTBOUND_BLOCK)) {
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
@ -1756,7 +1775,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
// Check outbound connectivity in specific ipversion and l4proto. // Check outbound connectivity in specific ipversion and l4proto.
struct outbound_connectivity_query q = {0}; struct outbound_connectivity_query q = {0};
q.outbound = new_hdr.outbound; q.outbound = new_hdr.routing_result.outbound;
q.ipversion = ipversion; q.ipversion = ipversion;
q.l4proto = l4proto; q.l4proto = l4proto;
__u32 *alive; __u32 *alive;
@ -1892,7 +1911,7 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
// map element using income client ip (that is daddr). // map element using income client ip (that is daddr).
__builtin_memcpy(&key_dst.ip, &tuples.dip, IPV6_BYTE_LENGTH); __builtin_memcpy(&key_dst.ip, &tuples.dip, IPV6_BYTE_LENGTH);
key_dst.port = tcph.dest; key_dst.port = tcph.dest;
struct ip_port_outbound *original_dst = struct dst_routing_result *original_dst =
bpf_map_lookup_elem(&tcp_dst_map, &key_dst); bpf_map_lookup_elem(&tcp_dst_map, &key_dst);
if (!original_dst) { if (!original_dst) {
bpf_printk("[%X]Bad Connection: to: %pI6:%u", bpf_ntohl(tcph.seq), bpf_printk("[%X]Bad Connection: to: %pI6:%u", bpf_ntohl(tcph.seq),
@ -1917,7 +1936,7 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
/// NOTICE: Actually, we do not need symmetrical headers in client and /// NOTICE: Actually, we do not need symmetrical headers in client and
/// server. We use it for convinience. This behavior may change in the /// server. We use it for convinience. This behavior may change in the
/// future. Outbound here is useless and redundant. /// future. Outbound here is useless and redundant.
struct ip_port_outbound ori_src; struct dst_routing_result ori_src;
// Get source ip/port from our packet header. // Get source ip/port from our packet header.

View File

@ -14,7 +14,6 @@ import (
"github.com/v2rayA/dae/common/consts" "github.com/v2rayA/dae/common/consts"
"github.com/v2rayA/dae/component/outbound/dialer" "github.com/v2rayA/dae/component/outbound/dialer"
"github.com/v2rayA/dae/component/sniffing" "github.com/v2rayA/dae/component/sniffing"
internal "github.com/v2rayA/dae/pkg/ebpf_internal"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"
"net/netip" "net/netip"
@ -44,24 +43,21 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
routingResult, err := c.core.RetrieveRoutingResult(src, dst, unix.IPPROTO_TCP) routingResult, err := c.core.RetrieveRoutingResult(src, dst, unix.IPPROTO_TCP)
if err != nil { if err != nil {
// WAN. Old method. // WAN. Old method.
var value bpfIpPortOutbound var value bpfDstRoutingResult
ip6 := src.Addr().As16() ip6 := src.Addr().As16()
if e := c.core.bpf.TcpDstMap.Lookup(bpfIpPort{ if e := c.core.bpf.TcpDstMap.Lookup(bpfIpPort{
Ip: struct{ U6Addr8 [16]uint8 }{U6Addr8: ip6}, Ip: struct{ U6Addr8 [16]uint8 }{U6Addr8: ip6},
Port: internal.Htons(src.Port()), Port: common.Htons(src.Port()),
}, &value); e != nil { }, &value); e != nil {
return fmt.Errorf("failed to retrieve target info %v: %v, %v", src.String(), err, e) return fmt.Errorf("failed to retrieve target info %v: %v, %v", src.String(), err, e)
} }
routingResult = &bpfRoutingResult{ routingResult = &value.RoutingResult
Mark: value.Mark,
Outbound: value.Outbound,
}
dstAddr, ok := netip.AddrFromSlice(common.Ipv6Uint32ArrayToByteSlice(value.Ip)) dstAddr, ok := netip.AddrFromSlice(common.Ipv6Uint32ArrayToByteSlice(value.Ip))
if !ok { if !ok {
return fmt.Errorf("failed to parse dest ip: %v", value.Ip) return fmt.Errorf("failed to parse dest ip: %v", value.Ip)
} }
dst = netip.AddrPortFrom(dstAddr, internal.Htons(value.Port)) dst = netip.AddrPortFrom(dstAddr, common.Htons(value.Port))
} }
var outboundIndex = consts.OutboundIndex(routingResult.Outbound) var outboundIndex = consts.OutboundIndex(routingResult.Outbound)
@ -101,6 +97,9 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
"policy": outbound.GetSelectionPolicy(), "policy": outbound.GetSelectionPolicy(),
"dialer": d.Name(), "dialer": d.Name(),
"domain": domain, "domain": domain,
"pid": routingResult.Pid,
"pname": ProcessName2String(routingResult.Pname[:]),
"mac": Mac2String(routingResult.Mac[:]),
}).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr(), consts.LanWanFlag_NotApplicable), RefineAddrPortToShow(dst)) }).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr(), consts.LanWanFlag_NotApplicable), RefineAddrPortToShow(dst))
} }

View File

@ -7,8 +7,10 @@ package control
import ( import (
"encoding/binary" "encoding/binary"
"encoding/gob"
"errors" "errors"
"fmt" "fmt"
"github.com/mzz2017/softwind/pkg/zeroalloc/buffer"
"github.com/mzz2017/softwind/pool" "github.com/mzz2017/softwind/pool"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/v2rayA/dae/common" "github.com/v2rayA/dae/common"
@ -22,6 +24,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"time" "time"
"unsafe"
) )
const ( const (
@ -44,52 +47,32 @@ func ChooseNatTimeout(data []byte, sniffDns bool) (dmsg *dnsmessage.Message, tim
return nil, DefaultNatTimeout return nil, DefaultNatTimeout
} }
type AddrHdr struct { func ParseAddrHdr(data []byte) (hdr *bpfDstRoutingResult, dataOffset int, err error) {
Dest netip.AddrPort dataOffset = int(unsafe.Sizeof(bpfDstRoutingResult{}))
Outbound uint8
Mark uint32
}
func ParseAddrHdr(data []byte) (hdr *AddrHdr, dataOffset int, err error) {
ipSize := 16
dataOffset = consts.AddrHdrSize
if len(data) < dataOffset { if len(data) < dataOffset {
return nil, 0, fmt.Errorf("data is too short to parse AddrHdr") return nil, 0, fmt.Errorf("data is too short to parse AddrHdr")
} }
destAddr, _ := netip.AddrFromSlice(data[:ipSize]) _hdr := *(*bpfDstRoutingResult)(unsafe.Pointer(&data[0]))
port := binary.BigEndian.Uint16(data[ipSize:]) _hdr.Port = common.Ntohs(_hdr.Port)
outbound := data[ipSize+2] return &_hdr, dataOffset, nil
mark := binary.BigEndian.Uint32(data[ipSize+4:])
return &AddrHdr{
Dest: netip.AddrPortFrom(destAddr, port),
Outbound: outbound,
Mark: mark,
}, dataOffset, nil
}
func (hdr *AddrHdr) ToBytesFromPool() []byte {
ipSize := 16
buf := pool.GetZero(consts.AddrHdrSize) // byte align to a multiple of 4
ip := hdr.Dest.Addr().As16()
copy(buf, ip[:])
binary.BigEndian.PutUint16(buf[ipSize:], hdr.Dest.Port())
buf[ipSize+2] = hdr.Outbound
binary.BigEndian.PutUint32(buf[ipSize+4:], hdr.Mark)
return buf
} }
func sendPktWithHdrWithFlag(data []byte, mark uint32, from netip.AddrPort, lConn *net.UDPConn, to netip.AddrPort, lanWanFlag consts.LanWanFlag) error { func sendPktWithHdrWithFlag(data []byte, mark uint32, from netip.AddrPort, lConn *net.UDPConn, to netip.AddrPort, lanWanFlag consts.LanWanFlag) error {
hdr := AddrHdr{ hdr := bpfDstRoutingResult{
Dest: from, Ip: common.Ipv6ByteSliceToUint32Array(from.Addr().AsSlice()),
Mark: mark, Port: common.Htons(from.Port()),
Outbound: uint8(lanWanFlag), // Pass some message to the kernel program. RoutingResult: bpfRoutingResult{
Outbound: uint8(lanWanFlag), // Pass some message to the kernel program.
},
} }
bHdr := hdr.ToBytesFromPool() buf := pool.Get(int(unsafe.Sizeof(hdr)) + len(data))
defer pool.Put(bHdr)
buf := pool.Get(len(bHdr) + len(data))
defer pool.Put(buf) defer pool.Put(buf)
copy(buf, bHdr) b := buffer.NewBufferFrom(buf)
copy(buf[len(bHdr):], data) defer b.Put()
if err := gob.NewEncoder(b).Encode(&hdr); err != nil {
return err
}
copy(buf[int(unsafe.Sizeof(hdr)):], data)
//log.Println("from", from, "to", to) //log.Println("from", from, "to", to)
_, err := lConn.WriteToUDPAddrPort(buf, to) _, err := lConn.WriteToUDPAddrPort(buf, to)
return err return err
@ -368,6 +351,9 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
c.log.WithFields(logrus.Fields{ c.log.WithFields(logrus.Fields{
"to": destToSend.String(), "to": destToSend.String(),
"domain": domain, "domain": domain,
"pid": routingResult.Pid,
"pname": ProcessName2String(routingResult.Pname[:]),
"mac": Mac2String(routingResult.Mac[:]),
"from": realSrc.String(), "from": realSrc.String(),
"network": networkType.String(), "network": networkType.String(),
"err": err.Error(), "err": err.Error(),
@ -439,16 +425,25 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
"dialer": realDialer.Name(), "dialer": realDialer.Name(),
"qname": strings.ToLower(q.Name.String()), "qname": strings.ToLower(q.Name.String()),
"qtype": q.Type, "qtype": q.Type,
"pid": routingResult.Pid,
"pname": ProcessName2String(routingResult.Pname[:]),
"mac": Mac2String(routingResult.Mac[:]),
}).Infof("%v <-> %v", }).Infof("%v <-> %v",
RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag), RefineAddrPortToShow(destToSend), RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag), RefineAddrPortToShow(destToSend),
) )
} else if c.log.IsLevelEnabled(logrus.InfoLevel) { } else if c.log.IsLevelEnabled(logrus.InfoLevel) {
if isDns && len(dnsMessage.Questions) > 0 {
domain = strings.ToLower(dnsMessage.Questions[0].Name.String())
}
c.log.WithFields(logrus.Fields{ c.log.WithFields(logrus.Fields{
"network": string(l4proto) + string(ipversion), "network": string(l4proto) + string(ipversion),
"outbound": outbound.Name, "outbound": outbound.Name,
"policy": outbound.GetSelectionPolicy(), "policy": outbound.GetSelectionPolicy(),
"dialer": realDialer.Name(), "dialer": realDialer.Name(),
"domain": domain, "domain": domain,
"pid": routingResult.Pid,
"pname": ProcessName2String(routingResult.Pname[:]),
"mac": Mac2String(routingResult.Mac[:]),
}).Infof("%v <-> %v", }).Infof("%v <-> %v",
RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag), RefineAddrPortToShow(destToSend), RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag), RefineAddrPortToShow(destToSend),
) )

View File

@ -8,10 +8,11 @@ package control
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/hex"
"fmt" "fmt"
"github.com/mzz2017/softwind/netproxy" "github.com/mzz2017/softwind/netproxy"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/common/consts" "github.com/v2rayA/dae/common/consts"
internal "github.com/v2rayA/dae/pkg/ebpf_internal"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net/netip" "net/netip"
"os" "os"
@ -24,14 +25,14 @@ func (c *ControlPlaneCore) RetrieveRoutingResult(src, dst netip.AddrPort, l4prot
tuples := &bpfTuples{ tuples := &bpfTuples{
Sip: struct{ U6Addr8 [16]uint8 }{U6Addr8: srcIp6}, Sip: struct{ U6Addr8 [16]uint8 }{U6Addr8: srcIp6},
Sport: internal.Htons(src.Port()), Sport: common.Htons(src.Port()),
Dip: struct{ U6Addr8 [16]uint8 }{U6Addr8: dstIp6}, Dip: struct{ U6Addr8 [16]uint8 }{U6Addr8: dstIp6},
Dport: internal.Htons(dst.Port()), Dport: common.Htons(dst.Port()),
L4proto: l4proto, L4proto: l4proto,
} }
var routingResult bpfRoutingResult var routingResult bpfRoutingResult
if err := c.bpf.RoutingTuplesMap.Lookup(tuples, &routingResult); err != nil { if err := c.bpf.RoutingTuplesMap.LookupAndDelete(tuples, &routingResult); err != nil {
return nil, fmt.Errorf("reading map: key [%v, %v, %v]: %w", src.String(), l4proto, dst.String(), err) return nil, fmt.Errorf("reading map: key [%v, %v, %v]: %w", src.String(), l4proto, dst.String(), err)
} }
return &routingResult, nil return &routingResult, nil
@ -88,3 +89,18 @@ func GetNetwork(network string, mark uint32) string {
}.Encode() }.Encode()
} }
} }
func ProcessName2String(pname []uint8) string {
return string(bytes.TrimRight(pname[:], string([]byte{0})))
}
func Mac2String(mac []uint8) string {
ori := []byte(hex.EncodeToString(mac))
// Insert ":".
b := make([]byte, len(ori)/2*3)
for i, j := 0, 0; i < len(ori); i, j = i+2, j+3 {
copy(b[j:j+2], ori[i:i+2])
b[j+2] = ':'
}
return string(b)
}

View File

@ -3,29 +3,21 @@
package internal package internal
import ( import (
"encoding/binary" "github.com/v2rayA/dae/common"
"syscall" "syscall"
"unsafe"
) )
func OpenRawSock(index int) (int, error) { func OpenRawSock(index int) (int, error) {
sock, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, int(Htons(syscall.ETH_P_ALL))) sock, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, int(common.Htons(syscall.ETH_P_ALL)))
if err != nil { if err != nil {
return 0, err return 0, err
} }
sll := syscall.SockaddrLinklayer{ sll := syscall.SockaddrLinklayer{
Ifindex: index, Ifindex: index,
Protocol: Htons(syscall.ETH_P_ALL), Protocol: common.Htons(syscall.ETH_P_ALL),
} }
if err := syscall.Bind(sock, &sll); err != nil { if err := syscall.Bind(sock, &sll); err != nil {
return 0, err return 0, err
} }
return sock, nil return sock, nil
} }
// Htons converts the unsigned short integer hostshort from host byte order to network byte order.
func Htons(i uint16) uint16 {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, i)
return *(*uint16)(unsafe.Pointer(&b[0]))
}