mirror of
https://github.com/daeuniverse/dae.git
synced 2024-12-22 15:44:42 +07:00
refactor/optimize: remove dead code (#411)
This commit is contained in:
parent
db8f474aa9
commit
883437b6a3
@ -165,12 +165,6 @@ const (
|
||||
|
||||
type LanWanFlag uint8
|
||||
|
||||
const (
|
||||
LanWanFlag_IsWan LanWanFlag = iota
|
||||
LanWanFlag_IsLan
|
||||
LanWanFlag_NotApplicable
|
||||
)
|
||||
|
||||
const (
|
||||
LinkHdrLen_None uint32 = 0
|
||||
LinkHdrLen_Ethernet uint32 = 14
|
||||
|
@ -9,12 +9,10 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
|
||||
"github.com/daeuniverse/dae/common/consts"
|
||||
)
|
||||
|
||||
func RefineSourceToShow(src netip.AddrPort, dst netip.Addr, lanWanFlag consts.LanWanFlag) (srcToShow string) {
|
||||
if lanWanFlag == consts.LanWanFlag_IsWan || src.Addr() == dst {
|
||||
func RefineSourceToShow(src netip.AddrPort, dst netip.Addr) (srcToShow string) {
|
||||
if src.Addr() == dst {
|
||||
// If nothing else, this means this packet is sent from localhost.
|
||||
return net.JoinHostPort("localhost", strconv.Itoa(int(src.Port())))
|
||||
} else {
|
||||
|
@ -5,4 +5,4 @@
|
||||
|
||||
package control
|
||||
|
||||
//go:generate go run -mod=mod github.com/cilium/ebpf/cmd/bpf2go -cc "$BPF_CLANG" "$BPF_STRIP_FLAG" -cflags "$BPF_CFLAGS" -target "$BPF_TARGET" -type dst_routing_result bpf kern/tproxy.c -- -I./headers
|
||||
//go:generate go run -mod=mod github.com/cilium/ebpf/cmd/bpf2go -cc "$BPF_CLANG" "$BPF_STRIP_FLAG" -cflags "$BPF_CFLAGS" -target "$BPF_TARGET" bpf kern/tproxy.c -- -I./headers
|
||||
|
@ -510,38 +510,6 @@ func (c *controlPlaneCore) _bindLan(ifname string) error {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// Insert filters.
|
||||
filterEgress := &netlink.BpfFilter{
|
||||
FilterAttrs: netlink.FilterAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Parent: netlink.HANDLE_MIN_EGRESS,
|
||||
Handle: netlink.MakeHandle(0x2023, 0b010+uint16(c.flip)),
|
||||
Protocol: unix.ETH_P_ALL,
|
||||
// Priority should be front of WAN's
|
||||
Priority: 1,
|
||||
},
|
||||
Fd: c.bpf.bpfPrograms.TproxyLanEgress.FD(),
|
||||
Name: consts.AppName + "_lan_egress",
|
||||
DirectAction: true,
|
||||
}
|
||||
// Remove and add.
|
||||
_ = netlink.FilterDel(filterEgress)
|
||||
if !c.isReload {
|
||||
// Clean up thoroughly.
|
||||
filterEgressFlipped := deepcopy.Copy(filterEgress).(*netlink.BpfFilter)
|
||||
filterEgressFlipped.FilterAttrs.Handle ^= 1
|
||||
_ = netlink.FilterDel(filterEgressFlipped)
|
||||
}
|
||||
if err := netlink.FilterAdd(filterEgress); err != nil {
|
||||
return fmt.Errorf("cannot attach ebpf object to filter egress: %w", err)
|
||||
}
|
||||
c.deferFuncs = append(c.deferFuncs, func() error {
|
||||
if err := netlink.FilterDel(filterEgress); err != nil {
|
||||
return fmt.Errorf("FilterDel(%v:%v): %w", ifname, filterEgress.Name, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,6 @@ func (c *DnsController) UpdateDnsCacheTtl(host string, dnsTyp uint16, answers []
|
||||
}
|
||||
|
||||
type udpRequest struct {
|
||||
lanWanFlag consts.LanWanFlag
|
||||
realSrc netip.AddrPort
|
||||
realDst netip.AddrPort
|
||||
src netip.AddrPort
|
||||
@ -347,7 +346,7 @@ func (c *DnsController) Handle_(dnsMessage *dnsmessage.Msg, req *udpRequest) (er
|
||||
if c.log.IsLevelEnabled(logrus.TraceLevel) && len(dnsMessage.Question) > 0 {
|
||||
q := dnsMessage.Question[0]
|
||||
c.log.Tracef("Received UDP(DNS) %v <-> %v: %v %v",
|
||||
RefineSourceToShow(req.realSrc, req.realDst.Addr(), req.lanWanFlag), req.realDst.String(), strings.ToLower(q.Name), QtypeToString(q.Qtype),
|
||||
RefineSourceToShow(req.realSrc, req.realDst.Addr()), req.realDst.String(), strings.ToLower(q.Name), QtypeToString(q.Qtype),
|
||||
)
|
||||
}
|
||||
|
||||
@ -410,7 +409,7 @@ func (c *DnsController) Handle_(dnsMessage *dnsmessage.Msg, req *udpRequest) (er
|
||||
// resp is valid.
|
||||
cache2 := c.LookupDnsRespCache(c.cacheKey(qname, qtype2), true)
|
||||
if c.qtypePrefer == qtype || cache2 == nil || !cache2.IncludeAnyIp() {
|
||||
return sendPkt(resp, req.realDst, req.realSrc, req.src, req.lConn, req.lanWanFlag)
|
||||
return sendPkt(resp, req.realDst, req.realSrc, req.src, req.lConn)
|
||||
} else {
|
||||
return c.sendReject_(dnsMessage, req)
|
||||
}
|
||||
@ -454,14 +453,14 @@ func (c *DnsController) handle_(
|
||||
if resp := c.LookupDnsRespCache_(dnsMessage, cacheKey, false); resp != nil {
|
||||
// Send cache to client directly.
|
||||
if needResp {
|
||||
if err = sendPkt(resp, req.realDst, req.realSrc, req.src, req.lConn, req.lanWanFlag); err != nil {
|
||||
if err = sendPkt(resp, req.realDst, req.realSrc, req.src, req.lConn); err != nil {
|
||||
return fmt.Errorf("failed to write cached DNS resp: %w", err)
|
||||
}
|
||||
}
|
||||
if c.log.IsLevelEnabled(logrus.DebugLevel) && len(dnsMessage.Question) > 0 {
|
||||
q := dnsMessage.Question[0]
|
||||
c.log.Debugf("UDP(DNS) %v <-> Cache: %v %v",
|
||||
RefineSourceToShow(req.realSrc, req.realDst.Addr(), req.lanWanFlag), strings.ToLower(q.Name), QtypeToString(q.Qtype),
|
||||
RefineSourceToShow(req.realSrc, req.realDst.Addr()), strings.ToLower(q.Name), QtypeToString(q.Qtype),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
@ -502,7 +501,7 @@ func (c *DnsController) sendReject_(dnsMessage *dnsmessage.Msg, req *udpRequest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pack DNS packet: %w", err)
|
||||
}
|
||||
if err = sendPkt(data, req.realDst, req.realSrc, req.src, req.lConn, req.lanWanFlag); err != nil {
|
||||
if err = sendPkt(data, req.realDst, req.realSrc, req.src, req.lConn); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -735,9 +734,9 @@ func (c *DnsController) dialSend(invokingDepth int, req *udpRequest, data []byte
|
||||
}
|
||||
switch upstreamIndex {
|
||||
case consts.DnsResponseOutboundIndex_Accept:
|
||||
c.log.WithFields(fields).Infof("%v <-> %v", RefineSourceToShow(req.realSrc, req.realDst.Addr(), req.lanWanFlag), RefineAddrPortToShow(dialArgument.bestTarget))
|
||||
c.log.WithFields(fields).Infof("%v <-> %v", RefineSourceToShow(req.realSrc, req.realDst.Addr()), RefineAddrPortToShow(dialArgument.bestTarget))
|
||||
case consts.DnsResponseOutboundIndex_Reject:
|
||||
c.log.WithFields(fields).Infof("%v -> reject", RefineSourceToShow(req.realSrc, req.realDst.Addr(), req.lanWanFlag))
|
||||
c.log.WithFields(fields).Infof("%v -> reject", RefineSourceToShow(req.realSrc, req.realDst.Addr()))
|
||||
default:
|
||||
return fmt.Errorf("unknown upstream: %v", upstreamIndex.String())
|
||||
}
|
||||
@ -752,7 +751,7 @@ func (c *DnsController) dialSend(invokingDepth int, req *udpRequest, data []byte
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = sendPkt(data, req.realDst, req.realSrc, req.src, req.lConn, req.lanWanFlag); err != nil {
|
||||
if err = sendPkt(data, req.realDst, req.realSrc, req.src, req.lConn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -133,16 +133,6 @@ struct routing_result {
|
||||
__u8 dscp;
|
||||
};
|
||||
|
||||
struct dst_routing_result {
|
||||
__be32 ip[4];
|
||||
__be16 port;
|
||||
__u16 recognize;
|
||||
struct routing_result routing_result;
|
||||
};
|
||||
|
||||
// force emitting struct into the ELF.
|
||||
const struct dst_routing_result *_ __attribute__((unused));
|
||||
|
||||
struct tuples_key {
|
||||
union ip6 sip;
|
||||
union ip6 dip;
|
||||
@ -399,159 +389,6 @@ static __always_inline bool equal16(const __be32 x[4], const __be32 y[4]) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static __always_inline __u32 l4_checksum_rel_off(__u8 proto) {
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
return offsetof(struct tcphdr, check);
|
||||
|
||||
case IPPROTO_UDP:
|
||||
return offsetof(struct udphdr, check);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline __u32 l4_checksum_off(__u32 link_h_len, __u8 proto,
|
||||
__u8 ihl) {
|
||||
return link_h_len + ihl * 4 + l4_checksum_rel_off(proto);
|
||||
}
|
||||
|
||||
static __always_inline int disable_l4_checksum(struct __sk_buff *skb,
|
||||
__u32 link_h_len, __u8 l4proto,
|
||||
__u8 ihl) {
|
||||
__u32 l4_cksm_off = l4_checksum_off(link_h_len, l4proto, ihl);
|
||||
// Set checksum zero.
|
||||
__sum16 bak_cksm = 0;
|
||||
return bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0);
|
||||
}
|
||||
|
||||
static __always_inline int rewrite_ip(struct __sk_buff *skb, __u32 link_h_len,
|
||||
__u8 proto, __u8 ihl, __be32 old_ip[4],
|
||||
__be32 new_ip[4], bool is_dest,
|
||||
bool disable_l4_checksum) {
|
||||
// Nothing to do.
|
||||
if (equal16(old_ip, new_ip)) {
|
||||
return 0;
|
||||
}
|
||||
// bpf_printk("%pI6->%pI6", old_ip, new_ip);
|
||||
|
||||
__u32 l4_cksm_off = l4_checksum_off(link_h_len, proto, ihl);
|
||||
int ret;
|
||||
// BPF_F_PSEUDO_HDR indicates the part we want to modify is part of the
|
||||
// pseudo header.
|
||||
__u32 l4flags = BPF_F_PSEUDO_HDR;
|
||||
if (proto == IPPROTO_UDP) {
|
||||
l4flags |= BPF_F_MARK_MANGLED_0;
|
||||
}
|
||||
|
||||
if (skb->protocol == bpf_htons(ETH_P_IP)) {
|
||||
|
||||
__be32 _old_ip = old_ip[3];
|
||||
__be32 _new_ip = new_ip[3];
|
||||
|
||||
int ret;
|
||||
|
||||
if (!disable_l4_checksum) {
|
||||
if ((ret = bpf_l4_csum_replace(skb, l4_cksm_off, _old_ip, _new_ip,
|
||||
l4flags | sizeof(_new_ip)))) {
|
||||
bpf_printk("bpf_l4_csum_replace: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = bpf_l3_csum_replace(skb, IPV4_CSUM_OFF(link_h_len), _old_ip,
|
||||
_new_ip, sizeof(_new_ip)))) {
|
||||
return ret;
|
||||
}
|
||||
// bpf_printk("%pI4 -> %pI4", &_old_ip, &_new_ip);
|
||||
|
||||
ret = bpf_skb_store_bytes(
|
||||
skb, is_dest ? IPV4_DST_OFF(link_h_len) : IPV4_SRC_OFF(link_h_len),
|
||||
&_new_ip, sizeof(_new_ip), 0);
|
||||
if (ret) {
|
||||
bpf_printk("bpf_skb_store_bytes: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!disable_l4_checksum) {
|
||||
__s64 cksm =
|
||||
bpf_csum_diff(old_ip, IPV6_BYTE_LENGTH, new_ip, IPV6_BYTE_LENGTH, 0);
|
||||
if ((ret = bpf_l4_csum_replace(skb, l4_cksm_off, 0, cksm, l4flags))) {
|
||||
bpf_printk("bpf_l4_csum_replace: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// bpf_printk("%pI6 -> %pI6", old_ip, new_ip);
|
||||
|
||||
ret = bpf_skb_store_bytes(
|
||||
skb, is_dest ? IPV6_DST_OFF(link_h_len) : IPV6_SRC_OFF(link_h_len),
|
||||
new_ip, IPV6_BYTE_LENGTH, 0);
|
||||
if (ret) {
|
||||
bpf_printk("bpf_skb_store_bytes: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline int rewrite_port(struct __sk_buff *skb, __u32 link_h_len,
|
||||
__u8 proto, __u8 ihl, __be16 old_port,
|
||||
__be16 new_port, bool is_dest,
|
||||
bool disable_l4_checksum) {
|
||||
// Nothing to do.
|
||||
if (old_port == new_port) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
__u32 cksm_off = l4_checksum_off(link_h_len, proto, ihl),
|
||||
port_off = link_h_len + ihl * 4;
|
||||
if (!cksm_off) {
|
||||
return -EINVAL;
|
||||
}
|
||||
__u32 l4flags = 0;
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
if (is_dest) {
|
||||
port_off += offsetof(struct tcphdr, dest);
|
||||
} else {
|
||||
port_off += offsetof(struct tcphdr, source);
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
if (is_dest) {
|
||||
port_off += offsetof(struct udphdr, dest);
|
||||
} else {
|
||||
port_off += offsetof(struct udphdr, source);
|
||||
}
|
||||
l4flags |= BPF_F_MARK_MANGLED_0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// bpf_printk("%u -> %u", bpf_ntohs(old_port), bpf_ntohs(new_port));
|
||||
|
||||
int ret;
|
||||
|
||||
if (!disable_l4_checksum) {
|
||||
if ((ret = bpf_l4_csum_replace(skb, cksm_off, old_port, new_port,
|
||||
l4flags | sizeof(new_port)))) {
|
||||
bpf_printk("bpf_l4_csum_replace: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = bpf_skb_store_bytes(skb, port_off, &new_port, sizeof(new_port),
|
||||
0))) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
handle_ipv6_extensions(const struct __sk_buff *skb, __u32 offset, __u32 hdr,
|
||||
struct icmp6hdr *icmp6h, struct tcphdr *tcph,
|
||||
@ -715,176 +552,6 @@ parse_transport(const struct __sk_buff *skb, __u32 link_h_len,
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline int adjust_udp_len(struct __sk_buff *skb,
|
||||
__u32 link_h_len, __u16 oldlen,
|
||||
__u32 ihl, __u16 len_diff,
|
||||
bool disable_l4_checksum) {
|
||||
if (unlikely(!len_diff)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Boundary check.
|
||||
if (len_diff > 0) {
|
||||
if (unlikely(bpf_ntohs(oldlen) + len_diff < len_diff)) { // overflow
|
||||
bpf_printk("udp length overflow");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (unlikely((__s32)bpf_ntohs(oldlen) + len_diff < 0)) { // not enough
|
||||
bpf_printk("udp length not enough");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
__be16 newlen = bpf_htons(bpf_ntohs(oldlen) + len_diff);
|
||||
|
||||
// Calculate checksum and store the new value.
|
||||
int ret;
|
||||
__u32 udp_csum_off = l4_checksum_off(link_h_len, IPPROTO_UDP, ihl);
|
||||
|
||||
if (!disable_l4_checksum) { // replace twice because len exists both pseudo
|
||||
// hdr and hdr.
|
||||
if ((ret = bpf_l4_csum_replace(
|
||||
skb, udp_csum_off, oldlen, newlen,
|
||||
sizeof(oldlen) | BPF_F_PSEUDO_HDR | // udp len is in the pseudo hdr
|
||||
BPF_F_MARK_MANGLED_0))) {
|
||||
bpf_printk("bpf_l4_csum_replace newudplen: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = bpf_l4_csum_replace(skb, udp_csum_off, oldlen, newlen,
|
||||
sizeof(oldlen) | BPF_F_MARK_MANGLED_0))) {
|
||||
bpf_printk("bpf_l4_csum_replace newudplen: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = bpf_skb_store_bytes(
|
||||
skb, link_h_len + ihl * 4 + offsetof(struct udphdr, len), &newlen,
|
||||
sizeof(oldlen), 0))) {
|
||||
bpf_printk("bpf_skb_store_bytes newudplen: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline int adjust_ipv4_len(struct __sk_buff *skb,
|
||||
__u32 link_h_len, __u16 oldlen,
|
||||
__u16 len_diff) {
|
||||
if (unlikely(!len_diff)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Boundary check.
|
||||
if (len_diff > 0) {
|
||||
if (unlikely(bpf_ntohs(oldlen) + len_diff < len_diff)) { // overflow
|
||||
bpf_printk("ip length overflow");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (unlikely((__s32)bpf_ntohs(oldlen) + len_diff < 0)) { // not enough
|
||||
bpf_printk("ip length not enough");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
__be16 newlen = bpf_htons(bpf_ntohs(oldlen) + len_diff);
|
||||
|
||||
// Calculate checksum and store the new value.
|
||||
int ret;
|
||||
if ((ret = bpf_l3_csum_replace(skb, IPV4_CSUM_OFF(link_h_len), oldlen, newlen,
|
||||
sizeof(oldlen)))) {
|
||||
bpf_printk("bpf_l3_csum_replace newudplen: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = bpf_skb_store_bytes(skb,
|
||||
link_h_len + offsetof(struct iphdr, tot_len),
|
||||
&newlen, sizeof(oldlen), 0))) {
|
||||
bpf_printk("bpf_skb_store_bytes newiplen: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
decap_after_udp_hdr(struct __sk_buff *skb, __u32 link_h_len, __u8 ihl,
|
||||
__be16 ipv4hdr_tot_len, void *to, __u32 decap_hdrlen,
|
||||
bool (*prevent_pop)(void *to), bool disable_l4_checksum) {
|
||||
if (unlikely(decap_hdrlen % 4 != 0)) {
|
||||
bpf_printk("encap_after_udp_hdr: unexpected decap_hdrlen value %u :must "
|
||||
"be a multiple of 4",
|
||||
decap_hdrlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
int ret = 0;
|
||||
long ip_off = link_h_len;
|
||||
// Calculate offsets using add instead of subtract to avoid verifier problems.
|
||||
long ipp_len = ihl * 4;
|
||||
|
||||
// Must check lower boundary for packet offset (and set the type of the
|
||||
// variables to signed long).
|
||||
if (skb->data + ip_off + ipp_len > skb->data_end) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Backup for further use.
|
||||
struct udphdr reserved_udphdr;
|
||||
if ((ret = bpf_skb_load_bytes(skb, ip_off + ipp_len, &reserved_udphdr,
|
||||
sizeof(struct udphdr)))) {
|
||||
bpf_printk("bpf_skb_load_bytes: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Load the hdr to decap.
|
||||
if ((ret = bpf_skb_load_bytes(skb, ip_off + ipp_len + sizeof(struct udphdr),
|
||||
to, decap_hdrlen))) {
|
||||
bpf_printk("bpf_skb_load_bytes decap_hdr: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Move the udphdr to the front of the real UDP payload.
|
||||
if ((ret =
|
||||
bpf_skb_store_bytes(skb, ip_off + ipp_len + decap_hdrlen,
|
||||
&reserved_udphdr, sizeof(reserved_udphdr), 0))) {
|
||||
bpf_printk("bpf_skb_store_bytes reserved_udphdr: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (prevent_pop == NULL || !prevent_pop(to)) {
|
||||
// Adjust room to decap the header.
|
||||
if ((ret = bpf_skb_adjust_room(skb, -decap_hdrlen, BPF_ADJ_ROOM_NET,
|
||||
BPF_F_ADJ_ROOM_NO_CSUM_RESET))) {
|
||||
bpf_printk("UDP ADJUST ROOM(decap): %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Rewrite ip len.
|
||||
if (skb->protocol == bpf_htons(ETH_P_IP)) {
|
||||
if ((ret = adjust_ipv4_len(skb, link_h_len, ipv4hdr_tot_len,
|
||||
-decap_hdrlen))) {
|
||||
bpf_printk("adjust_ip_len: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite udp len.
|
||||
if ((ret = adjust_udp_len(skb, link_h_len, reserved_udphdr.len, ihl,
|
||||
-decap_hdrlen, disable_l4_checksum))) {
|
||||
bpf_printk("adjust_udp_len: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!disable_l4_checksum) {
|
||||
// Rewrite udp checksum.
|
||||
__u32 udp_csum_off = l4_checksum_off(link_h_len, IPPROTO_UDP, ihl);
|
||||
__s64 cksm = bpf_csum_diff(to, decap_hdrlen, 0, 0, 0);
|
||||
if ((ret = bpf_l4_csum_replace(skb, udp_csum_off, 0, cksm,
|
||||
BPF_F_MARK_MANGLED_0))) {
|
||||
bpf_printk("bpf_l4_csum_replace 2: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Do not use __always_inline here because this function is too heavy.
|
||||
// low -> high: outbound(8b) mark(32b) unused(23b) sign(1b)
|
||||
static __s64 __attribute__((noinline))
|
||||
@ -1134,11 +801,6 @@ route(const __u32 flag[8], const void *l4hdr, const __be32 saddr[4],
|
||||
#undef _dscp
|
||||
}
|
||||
|
||||
static bool __always_inline is_not_to_lan(void *_ori_src) {
|
||||
struct dst_routing_result *ori_src = _ori_src;
|
||||
return ori_src->routing_result.outbound == IS_WAN;
|
||||
}
|
||||
|
||||
static __always_inline __u32 get_link_h_len(__u32 ifindex,
|
||||
volatile __u32 *link_h_len) {
|
||||
__u32 *plink_h_len = bpf_map_lookup_elem(&linklen_map, &ifindex);
|
||||
@ -1188,78 +850,6 @@ assign_socket(struct __sk_buff *skb, struct bpf_sock_tuple *tuple,
|
||||
return assign_socket_udp(skb, tuple, len);
|
||||
}
|
||||
|
||||
// SNAT for UDP packet.
|
||||
SEC("tc/egress")
|
||||
int tproxy_lan_egress(struct __sk_buff *skb) {
|
||||
if (skb->ingress_ifindex != NOWHERE_IFINDEX) {
|
||||
return TC_ACT_PIPE;
|
||||
}
|
||||
struct ethhdr ethh;
|
||||
struct iphdr iph;
|
||||
struct ipv6hdr ipv6h;
|
||||
struct icmp6hdr icmp6h;
|
||||
struct tcphdr tcph;
|
||||
struct udphdr udph;
|
||||
__u8 ihl;
|
||||
__u8 l4proto;
|
||||
__u32 link_h_len;
|
||||
if (get_link_h_len(skb->ifindex, &link_h_len)) {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
int ret = parse_transport(skb, link_h_len, ðh, &iph, &ipv6h, &icmp6h,
|
||||
&tcph, &udph, &ihl, &l4proto);
|
||||
if (ret) {
|
||||
bpf_printk("parse_transport: %d", ret);
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
switch (l4proto) {
|
||||
case IPPROTO_ICMPV6:
|
||||
if (icmp6h.icmp6_type == 137) {
|
||||
// REDIRECT (NDP)
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
return TC_ACT_PIPE;
|
||||
case IPPROTO_UDP:
|
||||
break;
|
||||
default:
|
||||
return TC_ACT_PIPE;
|
||||
}
|
||||
|
||||
__be16 tproxy_port = PARAM.tproxy_port;
|
||||
if (!tproxy_port) {
|
||||
return TC_ACT_PIPE;
|
||||
}
|
||||
struct tuples tuples;
|
||||
get_tuples(skb, &tuples, &iph, &ipv6h, &tcph, &udph, l4proto);
|
||||
if (tproxy_port != tuples.five.sport) {
|
||||
return TC_ACT_PIPE;
|
||||
}
|
||||
|
||||
struct dst_routing_result ori_src;
|
||||
if ((ret = decap_after_udp_hdr(
|
||||
skb, link_h_len, ihl,
|
||||
skb->protocol == bpf_htons(ETH_P_IP) ? iph.tot_len : 0, &ori_src,
|
||||
sizeof(ori_src), is_not_to_lan, true))) {
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
if (is_not_to_lan(&ori_src)) {
|
||||
return TC_ACT_PIPE;
|
||||
}
|
||||
if ((ret = rewrite_ip(skb, link_h_len, l4proto, ihl,
|
||||
tuples.five.sip.u6_addr32, ori_src.ip, false, true))) {
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
if ((ret = rewrite_port(skb, link_h_len, l4proto, ihl, tuples.five.sport,
|
||||
ori_src.port, false, true))) {
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
disable_l4_checksum(skb, link_h_len, l4proto, ihl);
|
||||
// bpf_printk("from %pI6 to %pI6", tuples.five.sip, ori_src.ip);
|
||||
// bpf_printk("from %u to %u", bpf_ntohs(tuples.five.sport),
|
||||
// bpf_ntohs(ori_src.port));
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
SEC("tc/ingress")
|
||||
int tproxy_lan_ingress(struct __sk_buff *skb) {
|
||||
struct ethhdr ethh;
|
||||
|
@ -162,7 +162,7 @@ func (c *ControlPlane) RouteDialTcp(p *RouteDialParam) (conn netproxy.Conn, err
|
||||
"dscp": routingResult.Dscp,
|
||||
"pname": ProcessName2String(routingResult.Pname[:]),
|
||||
"mac": Mac2String(routingResult.Mac[:]),
|
||||
}).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr(), consts.LanWanFlag_NotApplicable), dialTarget)
|
||||
}).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr()), dialTarget)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), consts.DefaultDialTimeout)
|
||||
defer cancel()
|
||||
|
@ -6,7 +6,6 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
@ -19,7 +18,6 @@ import (
|
||||
ob "github.com/daeuniverse/dae/component/outbound"
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/daeuniverse/dae/component/sniffing"
|
||||
internal "github.com/daeuniverse/dae/pkg/ebpf_internal"
|
||||
"github.com/daeuniverse/softwind/pool"
|
||||
dnsmessage "github.com/miekg/dns"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -50,44 +48,8 @@ func ChooseNatTimeout(data []byte, sniffDns bool) (dmsg *dnsmessage.Msg, timeout
|
||||
return nil, DefaultNatTimeout
|
||||
}
|
||||
|
||||
func sendPktWithHdrWithFlag(data []byte, realFrom netip.AddrPort, lConn *net.UDPConn, to netip.AddrPort, lanWanFlag consts.LanWanFlag) error {
|
||||
realFrom16 := realFrom.Addr().As16()
|
||||
hdr := bpfDstRoutingResult{
|
||||
Ip: common.Ipv6ByteSliceToUint32Array(realFrom16[:]),
|
||||
Port: common.Htons(realFrom.Port()),
|
||||
RoutingResult: bpfRoutingResult{
|
||||
Outbound: uint8(lanWanFlag), // Pass some message to the kernel program.
|
||||
},
|
||||
}
|
||||
// Do not put this 'buf' because it has been taken by buffer.
|
||||
b := pool.GetBuffer()
|
||||
defer pool.PutBuffer(b)
|
||||
// Use internal.NativeEndian due to already big endian.
|
||||
if err := binary.Write(b, internal.NativeEndian, hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Write(data)
|
||||
//logrus.Debugln("sendPktWithHdrWithFlag: from", realFrom, "to", to)
|
||||
if ipversion := consts.IpVersionFromAddr(to.Addr()); consts.IpVersionFromAddr(lConn.LocalAddr().(*net.UDPAddr).AddrPort().Addr()) != ipversion {
|
||||
// ip versions unmatched.
|
||||
if ipversion == consts.IpVersionStr_4 {
|
||||
// 4 to 6
|
||||
to = netip.AddrPortFrom(netip.AddrFrom16(to.Addr().As16()), to.Port())
|
||||
} else {
|
||||
// Shouldn't happen.
|
||||
return fmt.Errorf("unmatched ipversions")
|
||||
}
|
||||
}
|
||||
_, err := lConn.WriteToUDPAddrPort(b.Bytes(), to)
|
||||
return err
|
||||
}
|
||||
|
||||
// sendPkt uses bind first, and fallback to send hdr if addr is in use.
|
||||
func sendPkt(data []byte, from netip.AddrPort, realTo, to netip.AddrPort, lConn *net.UDPConn, lanWanFlag consts.LanWanFlag) (err error) {
|
||||
|
||||
if lanWanFlag == consts.LanWanFlag_IsWan {
|
||||
return sendPktWithHdrWithFlag(data, from, lConn, to, lanWanFlag)
|
||||
}
|
||||
func sendPkt(data []byte, from netip.AddrPort, realTo, to netip.AddrPort, lConn *net.UDPConn) (err error) {
|
||||
|
||||
transparentTimeout := AnyfromTimeout
|
||||
if from.Port() == 53 {
|
||||
@ -113,18 +75,9 @@ func sendPkt(data []byte, from netip.AddrPort, realTo, to netip.AddrPort, lConn
|
||||
}
|
||||
|
||||
func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, realDst netip.AddrPort, routingResult *bpfRoutingResult, skipSniffing bool) (err error) {
|
||||
var lanWanFlag consts.LanWanFlag
|
||||
var realSrc netip.AddrPort
|
||||
var domain string
|
||||
useAssign := pktDst == realDst // Use sk_assign instead of modify target ip/port.
|
||||
if useAssign {
|
||||
lanWanFlag = consts.LanWanFlag_IsLan
|
||||
realSrc = src
|
||||
} else {
|
||||
lanWanFlag = consts.LanWanFlag_IsWan
|
||||
// From localhost, so dst IP is src IP.
|
||||
realSrc = netip.AddrPortFrom(pktDst.Addr(), src.Port())
|
||||
}
|
||||
realSrc = src
|
||||
|
||||
// To keep consistency with kernel program, we only sniff DNS request sent to 53.
|
||||
dnsMessage, natTimeout := ChooseNatTimeout(data, realDst.Port() == 53)
|
||||
@ -185,7 +138,6 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
|
||||
}
|
||||
if isDns {
|
||||
return c.dnsController.Handle_(dnsMessage, &udpRequest{
|
||||
lanWanFlag: lanWanFlag,
|
||||
realSrc: realSrc,
|
||||
realDst: realDst,
|
||||
src: src,
|
||||
@ -224,7 +176,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
|
||||
getNew:
|
||||
if retry > MaxRetry {
|
||||
c.log.WithFields(logrus.Fields{
|
||||
"src": RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag),
|
||||
"src": RefineSourceToShow(realSrc, realDst.Addr()),
|
||||
"network": networkType.String(),
|
||||
"dialer": ue.Dialer.Property().Name,
|
||||
"retry": retry,
|
||||
@ -235,7 +187,7 @@ getNew:
|
||||
// Handler handles response packets and send it to the client.
|
||||
Handler: func(data []byte, from netip.AddrPort) (err error) {
|
||||
// Do not return conn-unrelated err in this func.
|
||||
return sendPkt(data, from, realSrc, src, lConn, lanWanFlag)
|
||||
return sendPkt(data, from, realSrc, src, lConn)
|
||||
},
|
||||
NatTimeout: natTimeout,
|
||||
GetDialOption: func() (option *DialOption, err error) {
|
||||
@ -299,7 +251,7 @@ getNew:
|
||||
|
||||
if c.log.IsLevelEnabled(logrus.DebugLevel) {
|
||||
c.log.WithFields(logrus.Fields{
|
||||
"src": RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag),
|
||||
"src": RefineSourceToShow(realSrc, realDst.Addr()),
|
||||
"network": networkType.String(),
|
||||
"dialer": ue.Dialer.Property().Name,
|
||||
"retry": retry,
|
||||
@ -346,7 +298,7 @@ getNew:
|
||||
"pname": ProcessName2String(routingResult.Pname[:]),
|
||||
"mac": Mac2String(routingResult.Mac[:]),
|
||||
}
|
||||
c.log.WithFields(fields).Infof("%v <-> %v", RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag), dialTarget)
|
||||
c.log.WithFields(fields).Infof("%v <-> %v", RefineSourceToShow(realSrc, realDst.Addr()), dialTarget)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user