feat: dns routing (#26)

This commit is contained in:
mzz
2023-02-25 02:38:21 +08:00
committed by GitHub
parent 33ad434f8a
commit 8bd6a77398
48 changed files with 2758 additions and 1449 deletions

View File

@ -59,7 +59,7 @@
#define OUTBOUND_DIRECT 0
#define OUTBOUND_BLOCK 1
#define OUTBOUND_MUST_DIRECT 0xFC
#define OUTBOUND_CONTROL_PLANE_DIRECT 0xFD
#define OUTBOUND_CONTROL_PLANE_ROUTING 0xFD
#define OUTBOUND_LOGICAL_OR 0xFE
#define OUTBOUND_LOGICAL_AND 0xFF
#define OUTBOUND_LOGICAL_MASK 0xFE
@ -89,6 +89,7 @@ static const __u32 disable_l4_rx_checksum_key
__attribute__((unused, deprecated)) = 3;
static const __u32 control_plane_pid_key = 4;
static const __u32 control_plane_nat_direct_key = 5;
static const __u32 control_plane_dns_routing_key = 6;
// Outbound Connectivity Map:
@ -225,23 +226,6 @@ struct {
__uint(pinning, LIBBPF_PIN_BY_NAME);
} ipproto_hdrsize_map SEC(".maps");
// Dns upstream:
struct dns_upstream {
__be32 ip4[4];
__be32 ip6[4];
bool hasIp4;
bool hasIp6;
__be16 port;
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32);
__type(value, struct dns_upstream);
/// FIXME: l4proto is always udp.
__uint(max_entries, 1);
} dns_upstream_map SEC(".maps");
// Interface Ips:
struct if_params {
bool rx_cksm_offload;
@ -946,7 +930,7 @@ decap_after_udp_hdr(struct __sk_buff *skb, __u8 ipversion, __u8 ihl,
// low -> high: outbound(8b) mark(32b) unused(23b) sign(1b)
static __s64 __attribute__((noinline))
routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
const __be32 _daddr[4], const __be32 mac[4]) {
const __be32 daddr[4], const __be32 mac[4]) {
#define _l4proto_type flag[0]
#define _ipversion_type flag[1]
#define _pname &flag[2]
@ -957,7 +941,6 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
__u32 key = MatchType_L4Proto;
__u16 h_dport;
__u16 h_sport;
__u32 daddr[4];
/// TODO: BPF_MAP_UPDATE_BATCH ?
if (unlikely((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key,
@ -992,27 +975,11 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
// Modify DNS upstream for routing.
if (h_dport == 53 && _l4proto_type == L4ProtoType_UDP) {
struct dns_upstream *upstream =
bpf_map_lookup_elem(&dns_upstream_map, &zero_key);
if (upstream && upstream->port != 0) {
h_dport = bpf_ntohs(upstream->port);
if (_ipversion_type == IpVersionType_4 && upstream->hasIp4) {
__builtin_memcpy(daddr, upstream->ip4, IPV6_BYTE_LENGTH);
} else if (_ipversion_type == IpVersionType_6 && upstream->hasIp6) {
__builtin_memcpy(daddr, upstream->ip6, IPV6_BYTE_LENGTH);
} else if (upstream->hasIp4) {
__builtin_memcpy(daddr, upstream->ip4, IPV6_BYTE_LENGTH);
} else if (upstream->hasIp6) {
__builtin_memcpy(daddr, upstream->ip6, IPV6_BYTE_LENGTH);
} else {
bpf_printk("bad dns upstream; use as-is.");
__builtin_memcpy(daddr, _daddr, IPV6_BYTE_LENGTH);
}
} else {
__builtin_memcpy(daddr, _daddr, IPV6_BYTE_LENGTH);
__u32 *control_plane_dns_routing =
bpf_map_lookup_elem(&param_map, &control_plane_dns_routing_key);
if (control_plane_dns_routing && *control_plane_dns_routing) {
return OUTBOUND_CONTROL_PLANE_ROUTING;
}
} else {
__builtin_memcpy(daddr, _daddr, IPV6_BYTE_LENGTH);
}
lpm_key_instance.trie_key.prefixlen = IPV6_BYTE_LENGTH * 8;
__builtin_memcpy(lpm_key_instance.data, daddr, IPV6_BYTE_LENGTH);
@ -1169,11 +1136,6 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
bpf_printk("MATCHED: match_set->type: %u, match_set->not: %d",
match_set->type, match_set->not );
#endif
if (match_set->outbound == OUTBOUND_DIRECT && h_dport == 53 &&
_l4proto_type == L4ProtoType_UDP) {
// DNS packet should go through control plane.
return OUTBOUND_CONTROL_PLANE_DIRECT | (match_set->mark << 8);
}
return match_set->outbound | (match_set->mark << 8);
}
bad_rule = false;
@ -1583,7 +1545,6 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
bpf_skc_lookup_tcp(skb, &tuple, tuple_size, BPF_F_CURRENT_NETNS, 0);
if (sk) {
// Not a tproxy WAN response. It is a tproxy LAN response.
tproxy_response = false;
bpf_sk_release(sk);
return TC_ACT_OK;
}
@ -1594,6 +1555,9 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
// Packets from tproxy port.
// We need to redirect it to original port.
// bpf_printk("tproxy_response: %pI6:%u", tuples.dip.u6_addr32,
// bpf_ntohs(tuples.dport));
// Write mac.
if ((ret = bpf_skb_store_bytes(skb, offsetof(struct ethhdr, h_dest),
ethh.h_source, sizeof(ethh.h_source), 0))) {
@ -1665,7 +1629,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
struct dst_routing_result *dst =
bpf_map_lookup_elem(&tcp_dst_map, &key_src);
if (!dst) {
// Do not impact previous connections.
// Do not impact previous connections and server connections.
return TC_ACT_OK;
}
outbound = dst->routing_result.outbound;
@ -1978,7 +1942,7 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
return TC_ACT_SHOT;
}
// bpf_printk("real from: %pI4:%u", &ori_src.ip, bpf_ntohs(ori_src.port));
// bpf_printk("real from: %pI6:%u", ori_src.ip, bpf_ntohs(ori_src.port));
// Print packet in hex for debugging (checksum or something else).
// bpf_printk("UDP EGRESS OK");