fix: checksum, ipv6 and domain matching problem

This commit is contained in:
mzz2017
2023-01-30 17:31:42 +08:00
parent 2de1a73dd2
commit 2105b5108b
6 changed files with 33 additions and 24 deletions

View File

@ -30,4 +30,5 @@ See [example.dae](https://github.com/v2rayA/dae/blob/main/example.dae).
1. Domain routing performance optimization. 1. Domain routing performance optimization.
1. DisableL4Checksum by link. 1. DisableL4Checksum by link.
1. Handle the case that nodes do not support UDP. 1. Handle the case that nodes do not support UDP.
1. L4Checksum problem.
1. ... 1. ...

View File

@ -42,6 +42,13 @@ func Ipv6ByteSliceToUint32Array(_ip []byte) (ip [4]uint32) {
return ip return ip
} }
func Ipv6Uint32ArrayToByteSlice(_ip [4]uint32) (ip []byte) {
for j := 0; j < 4; j++ {
ip = binary.LittleEndian.AppendUint32(ip, _ip[j])
}
return ip
}
func Deduplicate(list []string) []string { func Deduplicate(list []string) []string {
res := make([]string, 0, len(list)) res := make([]string, 0, len(list))
m := make(map[string]struct{}) m := make(map[string]struct{})

View File

@ -18,7 +18,7 @@ func (c *ControlPlane) MatchDomainBitmap(domain string) (bitmap [consts.MaxRouti
var hit bool var hit bool
switch s.Key { switch s.Key {
case consts.RoutingDomain_Suffix: case consts.RoutingDomain_Suffix:
if strings.HasSuffix(domain, d) { if domain == d || strings.HasSuffix(domain, "."+d) {
hit = true hit = true
} }
case consts.RoutingDomain_Full: case consts.RoutingDomain_Full:
@ -34,6 +34,7 @@ func (c *ControlPlane) MatchDomainBitmap(domain string) (bitmap [consts.MaxRouti
for _, d := range s.Domains { for _, d := range s.Domains {
if regexp.MustCompile(d).MatchString(strings.ToLower(domain)) { if regexp.MustCompile(d).MatchString(strings.ToLower(domain)) {
hit = true hit = true
break
} }
} }
} }

View File

@ -894,8 +894,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
good_subrule = true; good_subrule = true;
} }
} else if ((p_u32 = bpf_map_lookup_elem(&l4proto_ipversion_map, &key))) { } else if ((p_u32 = bpf_map_lookup_elem(&l4proto_ipversion_map, &key))) {
// bpf_printk("CHECK: l4proto_ipversion_map, match_set->type: %u, not: %d, // bpf_printk("CHECK: l4proto_ipversion_map, match_set->type: %u, not: %d,"
// "
// "outbound: %u", // "outbound: %u",
// match_set->type, match_set->not, match_set->outbound); // match_set->type, match_set->not, match_set->outbound);
if (*p_u32 & match_set->__value) { if (*p_u32 & match_set->__value) {
@ -930,6 +929,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
} }
before_next_loop: before_next_loop:
// bpf_printk("good_subrule: %d, bad_rule: %d", good_subrule, bad_rule);
if (match_set->outbound != OUTBOUND_LOGICAL_OR) { if (match_set->outbound != OUTBOUND_LOGICAL_OR) {
// This match_set reaches the end of subrule. // This match_set reaches the end of subrule.
// We are now at end of rule, or next match_set belongs to another // We are now at end of rule, or next match_set belongs to another
@ -943,7 +943,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
// Reset good_subrule. // Reset good_subrule.
good_subrule = false; good_subrule = false;
} }
// bpf_printk("_bad_rule: %d", bad_rule);
if ((match_set->outbound & OUTBOUND_LOGICAL_MASK) != if ((match_set->outbound & OUTBOUND_LOGICAL_MASK) !=
OUTBOUND_LOGICAL_MASK) { OUTBOUND_LOGICAL_MASK) {
// Tail of a rule (line). // Tail of a rule (line).
@ -962,7 +962,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
} }
} }
bpf_printk( bpf_printk(
"Did coder forget to sync common/consts/ebpf.go with enum ROUTING_TYPE?"); "No match_set hits. Did coder forget to sync common/consts/ebpf.go with enum MatchType?");
return -EPERM; return -EPERM;
#undef _l4proto #undef _l4proto
#undef _ip_version #undef _ip_version
@ -1629,11 +1629,14 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
} else { } else {
return TC_ACT_OK; return TC_ACT_OK;
} }
__be16 sport;
__be16 dport; __be16 dport;
if (tcph) { if (tcph) {
sport = tcph->source;
dport = tcph->dest; dport = tcph->dest;
l4_proto = IPPROTO_TCP; l4_proto = IPPROTO_TCP;
} else if (udph) { } else if (udph) {
sport = udph->source;
dport = udph->dest; dport = udph->dest;
l4_proto = IPPROTO_UDP; l4_proto = IPPROTO_UDP;
} else { } else {
@ -1647,7 +1650,8 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
// sender and its ip is right host ip. // sender and its ip is right host ip.
// saddr is host ip and right sender ip. // saddr is host ip and right sender ip.
// dport is sender sport. See (1). // dport is sender sport. See (1).
// bpf_printk("should send to origin: %pI6:%u", saddr, bpf_ntohs(dport)); // bpf_printk("[%u]should send to origin: %pI6:%u", l4_proto, saddr,
// bpf_ntohs(dport));
if (tcph) { if (tcph) {
// Lookup original dest as sip and sport. // Lookup original dest as sip and sport.
@ -1671,23 +1675,18 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
} }
// Rewrite sip and sport. // Rewrite sip and sport.
__u32 *src_ip = saddr; if (rewrite_ip(skb, ipv6h, IPPROTO_TCP, ihl, saddr, original_dst->ip,
__u16 src_port = tcph->source;
if (rewrite_ip(skb, ipv6h, IPPROTO_TCP, ihl, src_ip, original_dst->ip,
false) < 0) { false) < 0) {
bpf_printk("Shot IP: %d", ret); bpf_printk("Shot IP: %d", ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
if (rewrite_port(skb, IPPROTO_TCP, ihl, src_port, original_dst->port, if (rewrite_port(skb, IPPROTO_TCP, ihl, sport, original_dst->port,
false) < 0) { false) < 0) {
bpf_printk("Shot Port: %d", ret); bpf_printk("Shot Port: %d", ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
} else if (udph) { } else if (udph) {
// Backup for further use.
__u32 *src_ip = saddr;
__u16 src_port = udph->source;
/// 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.
@ -1701,14 +1700,14 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
sizeof(ori_src)); sizeof(ori_src));
// Rewrite udp src ip // Rewrite udp src ip
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_UDP, ihl, src_ip, ori_src.ip, if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_UDP, ihl, saddr, ori_src.ip,
false))) { false))) {
bpf_printk("Shot IP: %d", ret); bpf_printk("Shot IP: %d", ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
// Rewrite udp src port // Rewrite udp src port
if ((ret = rewrite_port(skb, IPPROTO_UDP, ihl, src_port, ori_src.port, if ((ret = rewrite_port(skb, IPPROTO_UDP, ihl, sport, ori_src.port,
false))) { false))) {
bpf_printk("Shot Port: %d", ret); bpf_printk("Shot Port: %d", ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
@ -1761,10 +1760,10 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
} }
} }
// __u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl); __u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl);
// // Restore the checksum or set it zero. // Restore the checksum or set it zero.
// __sum16 bak_cksm = 0; __sum16 bak_cksm = 0;
// bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0); bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0);
return TC_ACT_OK; return TC_ACT_OK;
} }

View File

@ -6,7 +6,6 @@
package control package control
import ( import (
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"github.com/mzz2017/softwind/pkg/zeroalloc/io" "github.com/mzz2017/softwind/pkg/zeroalloc/io"
@ -29,9 +28,11 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
}, &value); err != nil { }, &value); err != nil {
return fmt.Errorf("reading map: key %v: %w", rAddr.String(), err) return fmt.Errorf("reading map: key %v: %w", rAddr.String(), err)
} }
var dstIP [4]byte dstSlice, ok := netip.AddrFromSlice(common.Ipv6Uint32ArrayToByteSlice(value.Ip))
binary.LittleEndian.PutUint32(dstIP[:], value.Ip[3]) if !ok {
dst := netip.AddrPortFrom(netip.AddrFrom4(dstIP), swap16(value.Port)) return fmt.Errorf("failed to parse dest ip: %v", value.Ip)
}
dst := netip.AddrPortFrom(dstSlice, swap16(value.Port))
switch consts.OutboundIndex(value.Outbound) { switch consts.OutboundIndex(value.Outbound) {
case consts.OutboundDirect: case consts.OutboundDirect:

View File

@ -81,7 +81,7 @@ func (c *ControlPlane) RelayToUDP(lConn *net.UDPConn, to netip.AddrPort, isDNS b
if isDNS { if isDNS {
data, err = c.DnsRespHandler(data) data, err = c.DnsRespHandler(data)
if err != nil { if err != nil {
c.log.Warnf("DnsRespHandler: %v", err) c.log.Debugf("DnsRespHandler: %v", err)
} }
} }
if dummyFrom != nil { if dummyFrom != nil {