diff --git a/control/bpf_utils.go b/control/bpf_utils.go index b99b0cc..101c131 100644 --- a/control/bpf_utils.go +++ b/control/bpf_utils.go @@ -195,8 +195,20 @@ func (p bpfIfParams) CheckVersionRequirement(version *internal.Version) (err err } type loadBpfOptions struct { - PinPath string - CollectionOptions *ebpf.CollectionOptions + PinPath string + BigEndianTproxyPort uint32 + CollectionOptions *ebpf.CollectionOptions +} + +func loadBpfObjectsWithConstants(obj interface{}, opts *ebpf.CollectionOptions, constants map[string]interface{}) error { + spec, err := loadBpf() + if err != nil { + return err + } + if err := spec.RewriteConstants(constants); err != nil { + return err + } + return spec.LoadAndAssign(obj, opts) } func fullLoadBpfObjects( @@ -205,7 +217,16 @@ func fullLoadBpfObjects( opts *loadBpfOptions, ) (err error) { retryLoadBpf: - if err = loadBpfObjects(bpf, opts.CollectionOptions); err != nil { + constants := map[string]interface{}{ + "PARAM": struct { + tproxyPort uint32 + controlPlanePid uint32 + }{ + tproxyPort: uint32(opts.BigEndianTproxyPort), + controlPlanePid: uint32(os.Getpid()), + }, + } + if err = loadBpfObjectsWithConstants(bpf, opts.CollectionOptions, constants); err != nil { if errors.Is(err, ebpf.ErrMapIncompatible) { // Map property is incompatible. Remove the old map and try again. prefix := "use pinned map " diff --git a/control/control_plane.go b/control/control_plane.go index 0812edc..bcd89a8 100644 --- a/control/control_plane.go +++ b/control/control_plane.go @@ -165,8 +165,9 @@ func NewControlPlane( } else { bpf = new(bpfObjects) if err = fullLoadBpfObjects(log, bpf, &loadBpfOptions{ - PinPath: pinPath, - CollectionOptions: collectionOpts, + PinPath: pinPath, + BigEndianTproxyPort: uint32(common.Htons(global.TproxyPort)), + CollectionOptions: collectionOpts, }); err != nil { if log.Level == logrus.PanicLevel { log.Panicln(err) @@ -192,11 +193,6 @@ func NewControlPlane( } }() - // Write params. - if err = core.bpf.ParamMap.Update(consts.ControlPlanePidKey, uint32(os.Getpid()), ebpf.UpdateAny); err != nil { - return nil, err - } - /// Bind to links. Binding should be advance of dialerGroups to avoid un-routable old connection. // Bind to LAN if len(global.LanInterface) > 0 { @@ -685,10 +681,6 @@ func (c *ControlPlane) Serve(readyChan chan<- bool, listener *Listener) (err err if err := c.core.bpf.ListenSocketMap.Update(consts.OneKey, uint64(udpFile.Fd()), ebpf.UpdateAny); err != nil { return err } - // Port. - if err := c.core.bpf.ParamMap.Update(consts.BigEndianTproxyPortKey, uint32(common.Htons(listener.port)), ebpf.UpdateAny); err != nil { - return err - } sentReady = true readyChan <- true diff --git a/control/kern/tproxy.c b/control/kern/tproxy.c index fec2a25..b38a16c 100644 --- a/control/kern/tproxy.c +++ b/control/kern/tproxy.c @@ -83,17 +83,7 @@ enum { // Param keys: static const __u32 zero_key = 0; -static const __u32 tproxy_port_key = 1; static const __u32 one_key = 1; -static const __u32 disable_l4_tx_checksum_key - __attribute__((unused, deprecated)) = 2; -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 - __attribute__((unused, deprecated)) = 5; -static const __u32 control_plane_dns_routing_key - __attribute__((unused, deprecated)) = 6; // Outbound Connectivity Map: @@ -163,6 +153,13 @@ struct tuples { __u8 dscp; }; +struct dae_param { + __u32 tproxy_port; + __u32 control_plane_pid; +}; + +static volatile const struct dae_param PARAM = {}; + struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); __type(key, @@ -196,15 +193,6 @@ struct { __uint(pinning, LIBBPF_PIN_BY_NAME); } routing_tuples_map SEC(".maps"); -// Params: -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __type(key, __u32); - __type(value, __u32); - __uint(max_entries, MAX_PARAM_LEN); - __uint(pinning, LIBBPF_PIN_BY_NAME); -} param_map SEC(".maps"); - // Link to type: #define LinkType_None 0 #define LinkType_Ethernet 1 @@ -1279,13 +1267,13 @@ int tproxy_lan_egress(struct __sk_buff *skb) { return TC_ACT_PIPE; } - __be16 *tproxy_port = bpf_map_lookup_elem(¶m_map, &tproxy_port_key); + __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) { + if (tproxy_port != tuples.five.sport) { return TC_ACT_PIPE; } @@ -1540,13 +1528,12 @@ static __always_inline bool pid_is_control_plane(struct __sk_buff *skb, *p = pid_pname; } // Get tproxy pid and compare if they are equal. - __u32 *pid_tproxy; - if (!(pid_tproxy = - bpf_map_lookup_elem(¶m_map, &control_plane_pid_key))) { + __u32 pid_tproxy; + if (!(pid_tproxy = PARAM.control_plane_pid)) { bpf_printk("control_plane_pid is not set."); return false; } - return pid_pname->pid == *pid_tproxy; + return pid_pname->pid == pid_tproxy; } else { if (p) { *p = NULL; @@ -1621,11 +1608,11 @@ int tproxy_wan_egress(struct __sk_buff *skb) { // We should know if this packet is from tproxy. // We do not need to check the source ip because we have skipped packets not // from localhost. - __be16 *tproxy_port = bpf_map_lookup_elem(¶m_map, &tproxy_port_key); + __be16 tproxy_port = PARAM.tproxy_port; if (!tproxy_port) { return TC_ACT_OK; } - bool tproxy_response = *tproxy_port == tuples.five.sport; + bool tproxy_response = tproxy_port == tuples.five.sport; // Double check to avoid conflicts when binding wan and lan to the same // interface. if (tproxy_response && l4proto == IPPROTO_TCP) { @@ -1965,11 +1952,11 @@ int tproxy_wan_ingress(struct __sk_buff *skb) { __u16 tproxy_typ = bpf_ntohs(*(__u16 *)ðh.h_source[4]); if (*(__u32 *)ðh.h_source[0] != bpf_htonl(0x02000203) || tproxy_typ > 1) { // Check for security. Reject packets that is UDP and sent to tproxy port. - __be16 *tproxy_port = bpf_map_lookup_elem(¶m_map, &tproxy_port_key); + __be16 tproxy_port = PARAM.tproxy_port; if (!tproxy_port) { goto accept; } - if (unlikely(*tproxy_port == tuples.five.dport)) { + if (unlikely(tproxy_port == tuples.five.dport)) { struct bpf_sock_tuple tuple = {0}; __u32 tuple_size; @@ -2103,7 +2090,7 @@ int tproxy_wan_ingress(struct __sk_buff *skb) { // saddr should be tproxy ip. __be32 *tproxy_ip = tuples.five.sip.u6_addr32; // __builtin_memcpy(tproxy_ip, saddr, sizeof(tproxy_ip)); - __be16 *tproxy_port = bpf_map_lookup_elem(¶m_map, &tproxy_port_key); + __be16 tproxy_port = PARAM.tproxy_port; if (!tproxy_port) { return TC_ACT_OK; } @@ -2118,7 +2105,7 @@ int tproxy_wan_ingress(struct __sk_buff *skb) { // Rewrite dst port. if ((ret = rewrite_port(skb, link_h_len, l4proto, ihl, tuples.five.dport, - *tproxy_port, true, true))) { + tproxy_port, true, true))) { bpf_printk("Shot Port: %d", ret); return TC_ACT_SHOT; }