github.com/yaling888/clash@v1.53.0/component/ebpf/bpf/tc.c (about) 1 #include <stdbool.h> 2 #include <linux/bpf.h> 3 #include <linux/if_ether.h> 4 #include <linux/ip.h> 5 #include <linux/in.h> 6 //#include <linux/tcp.h> 7 //#include <linux/udp.h> 8 #include <linux/pkt_cls.h> 9 10 #include "bpf_endian.h" 11 #include "bpf_helpers.h" 12 13 struct { 14 __uint(type, BPF_MAP_TYPE_ARRAY); 15 __type(key, __u32); 16 __type(value, __u32); 17 __uint(max_entries, 2); 18 __uint(pinning, LIBBPF_PIN_BY_NAME); 19 } tc_params_map SEC(".maps"); 20 21 static __always_inline bool is_lan_ip(__be32 addr) { 22 if (addr == 0xffffffff) 23 return true; 24 25 __u8 fist = (__u8)(addr & 0xff); 26 27 if (fist == 127 || fist == 10) 28 return true; 29 30 __u8 second = (__u8)((addr >> 8) & 0xff); 31 32 if (fist == 172 && second >= 16 && second <= 31) 33 return true; 34 35 if (fist == 192 && second == 168) 36 return true; 37 38 return false; 39 } 40 41 SEC("tc_clash_redirect_to_tun") 42 int tc_tun_func(struct __sk_buff *skb) { 43 void *data = (void *)(long)skb->data; 44 void *data_end = (void *)(long)skb->data_end; 45 struct ethhdr *eth = data; 46 47 if ((void *)(eth + 1) > data_end) 48 return TC_ACT_OK; 49 50 if (eth->h_proto == bpf_htons(ETH_P_ARP)) 51 return TC_ACT_OK; 52 53 __u32 key = 0, *clash_mark, *tun_ifindex; 54 55 clash_mark = bpf_map_lookup_elem(&tc_params_map, &key); 56 if (!clash_mark) 57 return TC_ACT_OK; 58 59 if (skb->mark == *clash_mark) 60 return TC_ACT_OK; 61 62 if (eth->h_proto == bpf_htons(ETH_P_IP)) { 63 struct iphdr *iph = (struct iphdr *)(eth + 1); 64 if ((void *)(iph + 1) > data_end) 65 return TC_ACT_OK; 66 67 if (iph->protocol == IPPROTO_ICMP) 68 return TC_ACT_OK; 69 70 __be32 daddr = iph->daddr; 71 72 if (is_lan_ip(daddr)) 73 return TC_ACT_OK; 74 75 // if (iph->protocol == IPPROTO_TCP) { 76 // struct tcphdr *tcph = (struct tcphdr *)(iph + 1); 77 // if ((void *)(tcph + 1) > data_end) 78 // return TC_ACT_OK; 79 // 80 // __u16 source = bpf_ntohs(tcph->source); 81 // if (source == 22 || source == 80 || source == 443 || source == 8080 || source == 8443 || source == 9090 || (source >= 7890 && source <= 7895)) 82 // return TC_ACT_OK; 83 // } else if (iph->protocol == IPPROTO_UDP) { 84 // struct udphdr *udph = (struct udphdr *)(iph + 1); 85 // if ((void *)(udph + 1) > data_end) 86 // return TC_ACT_OK; 87 // 88 // __u16 source = bpf_ntohs(udph->source); 89 // if (source == 53 || (source >= 135 && source <= 139)) 90 // return TC_ACT_OK; 91 // } 92 } 93 94 key = 1; 95 tun_ifindex = bpf_map_lookup_elem(&tc_params_map, &key); 96 if (!tun_ifindex) 97 return TC_ACT_OK; 98 99 //return bpf_redirect(*tun_ifindex, BPF_F_INGRESS); // __bpf_rx_skb 100 return bpf_redirect(*tun_ifindex, 0); // __bpf_tx_skb / __dev_xmit_skb 101 } 102 103 char _license[] SEC("license") = "GPL";