tc.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. #include "bpf_endian.h"
  10. #include "bpf_helpers.h"
  11. struct {
  12. __uint(type, BPF_MAP_TYPE_ARRAY);
  13. __type(key, __u32);
  14. __type(value, __u32);
  15. __uint(max_entries, 2);
  16. __uint(pinning, LIBBPF_PIN_BY_NAME);
  17. } tc_params_map SEC(".maps");
  18. static __always_inline bool is_lan_ip(__be32 addr) {
  19. if (addr == 0xffffffff)
  20. return true;
  21. __u8 fist = (__u8)(addr & 0xff);
  22. if (fist == 127 || fist == 10)
  23. return true;
  24. __u8 second = (__u8)((addr >> 8) & 0xff);
  25. if (fist == 172 && second >= 16 && second <= 31)
  26. return true;
  27. if (fist == 192 && second == 168)
  28. return true;
  29. return false;
  30. }
  31. SEC("tc_mihomo_redirect_to_tun")
  32. int tc_tun_func(struct __sk_buff *skb) {
  33. void *data = (void *)(long)skb->data;
  34. void *data_end = (void *)(long)skb->data_end;
  35. struct ethhdr *eth = data;
  36. if ((void *)(eth + 1) > data_end)
  37. return TC_ACT_OK;
  38. if (eth->h_proto == bpf_htons(ETH_P_ARP))
  39. return TC_ACT_OK;
  40. __u32 key = 0, *mihomo_mark, *tun_ifindex;
  41. mihomo_mark = bpf_map_lookup_elem(&tc_params_map, &key);
  42. if (!mihomo_mark)
  43. return TC_ACT_OK;
  44. if (skb->mark == *mihomo_mark)
  45. return TC_ACT_OK;
  46. if (eth->h_proto == bpf_htons(ETH_P_IP)) {
  47. struct iphdr *iph = (struct iphdr *)(eth + 1);
  48. if ((void *)(iph + 1) > data_end)
  49. return TC_ACT_OK;
  50. if (iph->protocol == IPPROTO_ICMP)
  51. return TC_ACT_OK;
  52. __be32 daddr = iph->daddr;
  53. if (is_lan_ip(daddr))
  54. return TC_ACT_OK;
  55. // if (iph->protocol == IPPROTO_TCP) {
  56. // struct tcphdr *tcph = (struct tcphdr *)(iph + 1);
  57. // if ((void *)(tcph + 1) > data_end)
  58. // return TC_ACT_OK;
  59. //
  60. // __u16 source = bpf_ntohs(tcph->source);
  61. // if (source == 22 || source == 80 || source == 443 || source == 8080 || source == 8443 || source == 9090 || (source >= 7890 && source <= 7895))
  62. // return TC_ACT_OK;
  63. // } else if (iph->protocol == IPPROTO_UDP) {
  64. // struct udphdr *udph = (struct udphdr *)(iph + 1);
  65. // if ((void *)(udph + 1) > data_end)
  66. // return TC_ACT_OK;
  67. //
  68. // __u16 source = bpf_ntohs(udph->source);
  69. // if (source == 53 || (source >= 135 && source <= 139))
  70. // return TC_ACT_OK;
  71. // }
  72. }
  73. key = 1;
  74. tun_ifindex = bpf_map_lookup_elem(&tc_params_map, &key);
  75. if (!tun_ifindex)
  76. return TC_ACT_OK;
  77. //return bpf_redirect(*tun_ifindex, BPF_F_INGRESS); // __bpf_rx_skb
  78. return bpf_redirect(*tun_ifindex, 0); // __bpf_tx_skb / __dev_xmit_skb
  79. }
  80. char _license[] SEC("license") = "GPL";