Skip to content

Commit

Permalink
bpf: Fix proxy redirection for egress programs
Browse files Browse the repository at this point in the history
 * Handling of the proxy redirection was missing entirely in the to-container
   section for IPv6. Add it.

 * The to-container section case was assuming that any proxy redirection is
   indicated by ipv{46}_policy() returning a non-zero proxy port. This is no
   longer true since commit 830adba. Fix this by using a separate return code
   to indicate proxy redirection and treating the proxy port as optional.

The above deficits lead to proxy redirection being ineffective when the setting
EnableEndpointRoutes was set.

Fixes: 830adba ("bpf: Support proxy using original source address and port.")
Fixes: 25a80df ("bpf: Add to-container section to bpf_lxc")
Fixes: #10105

Signed-off-by: Thomas Graf <thomas@cilium.io>
  • Loading branch information
tgraf committed Feb 11, 2020
1 parent 54d9254 commit c58d749
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 18 deletions.
46 changes: 29 additions & 17 deletions bpf/bpf_lxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ int handle_xgress(struct __sk_buff *skb)

#ifdef ENABLE_IPV6
static inline int __inline__
ipv6_policy(struct __sk_buff *skb, int ifindex, __u32 src_label, __u8 *reason)
ipv6_policy(struct __sk_buff *skb, int ifindex, __u32 src_label, __u8 *reason, __u16 *proxy_port)
{
struct ipv6_ct_tuple tuple = {};
void *data, *data_end;
Expand Down Expand Up @@ -835,8 +835,11 @@ ipv6_policy(struct __sk_buff *skb, int ifindex, __u32 src_label, __u8 *reason)
// Do not redirect again if the packet is coming from the egress proxy.
if ((ret == CT_REPLY || ret == CT_RELATED) && ct_state.proxy_redirect &&
!tc_index_skip_egress_proxy(skb)) {
// Stack will do a socket match and deliver locally
return skb_redirect_to_proxy(skb, 0);
// This is a reply, the proxy port does not need to be embedded
// into skb->mark and *proxy_port can be left unset.
send_trace_notify6(skb, TRACE_TO_PROXY, src_label, SECLABEL, &orig_sip,
0, ifindex, 0, monitor);
return POLICY_ACT_PROXY_REDIRECT;
}

if (unlikely(ct_state.rev_nat_index)) {
Expand Down Expand Up @@ -884,10 +887,10 @@ ipv6_policy(struct __sk_buff *skb, int ifindex, __u32 src_label, __u8 *reason)
return DROP_INVALID;

if (redirect_to_proxy(verdict, *reason)) {
// Trace the packet before its forwarded to proxy
*proxy_port = verdict;
send_trace_notify6(skb, TRACE_TO_PROXY, src_label, SECLABEL, &orig_sip,
0, ifindex, *reason, monitor);
return skb_redirect_to_proxy(skb, verdict);
return POLICY_ACT_PROXY_REDIRECT;
} else { // Not redirected to host / proxy.
send_trace_notify6(skb, TRACE_TO_LXC, src_label, SECLABEL, &orig_sip,
LXC_ID, ifindex, *reason, monitor);
Expand All @@ -905,11 +908,15 @@ int tail_ipv6_policy(struct __sk_buff *skb)
{
int ret, ifindex = skb->cb[CB_IFINDEX];
__u32 src_label = skb->cb[CB_SRC_LABEL];
__u16 proxy_port = 0;
__u8 reason = 0;


skb->cb[CB_SRC_LABEL] = 0;
ret = ipv6_policy(skb, ifindex, src_label, &reason);
ret = ipv6_policy(skb, ifindex, src_label, &reason, &proxy_port);

if (ret == POLICY_ACT_PROXY_REDIRECT)
ret = skb_redirect_to_proxy(skb, proxy_port);

if (IS_ERR(ret))
return send_drop_notify(skb, src_label, SECLABEL, LXC_ID,
Expand All @@ -925,6 +932,7 @@ int tail_ipv6_to_endpoint(struct __sk_buff *skb)
__u32 src_identity = skb->cb[CB_SRC_LABEL];
void *data, *data_end;
struct ipv6hdr *ip6;
__u16 proxy_port = 0;
__u8 reason;
int ret;

Expand Down Expand Up @@ -965,7 +973,10 @@ int tail_ipv6_to_endpoint(struct __sk_buff *skb)
#endif

skb->cb[CB_SRC_LABEL] = 0;
ret = ipv6_policy(skb, 0, src_identity, &reason);
ret = ipv6_policy(skb, 0, src_identity, &reason, &proxy_port);

if (ret == POLICY_ACT_PROXY_REDIRECT)
ret = skb_redirect_to_proxy_hairpin(skb, proxy_port);

out:
if (IS_ERR(ret))
Expand Down Expand Up @@ -1023,8 +1034,11 @@ ipv4_policy(struct __sk_buff *skb, int ifindex, __u32 src_label, __u8 *reason, _
// Do not redirect again if the packet is coming from the egress proxy.
if ((ret == CT_REPLY || ret == CT_RELATED) && ct_state.proxy_redirect &&
!tc_index_skip_egress_proxy(skb)) {
// Stack will do a socket match and deliver locally
return skb_redirect_to_proxy(skb, 0);
// This is a reply, the proxy port does not need to be embedded
// into skb->mark and *proxy_port can be left unset.
send_trace_notify4(skb, TRACE_TO_PROXY, src_label, SECLABEL, orig_sip,
0, ifindex, 0, monitor);
return POLICY_ACT_PROXY_REDIRECT;
}

#ifdef ENABLE_NAT46
Expand Down Expand Up @@ -1083,10 +1097,9 @@ ipv4_policy(struct __sk_buff *skb, int ifindex, __u32 src_label, __u8 *reason, _

if (redirect_to_proxy(verdict, *reason)) {
*proxy_port = verdict;
// Trace the packet before its forwarded to proxy
send_trace_notify4(skb, TRACE_TO_PROXY, src_label, SECLABEL, orig_sip,
0, ifindex, *reason, monitor);
return TC_ACT_OK;
return POLICY_ACT_PROXY_REDIRECT;
} else { // Not redirected to host / proxy.
send_trace_notify4(skb, TRACE_TO_LXC, src_label, SECLABEL, orig_sip,
LXC_ID, ifindex, *reason, monitor);
Expand All @@ -1109,14 +1122,14 @@ int tail_ipv4_policy(struct __sk_buff *skb)

skb->cb[CB_SRC_LABEL] = 0;
ret = ipv4_policy(skb, ifindex, src_label, &reason, &proxy_port);

if (ret == POLICY_ACT_PROXY_REDIRECT)
ret = skb_redirect_to_proxy(skb, proxy_port);

if (IS_ERR(ret))
return send_drop_notify(skb, src_label, SECLABEL, LXC_ID,
ret, TC_ACT_SHOT, METRIC_INGRESS);

if (proxy_port != 0) {
ret = skb_redirect_to_proxy(skb, proxy_port);
}

skb->cb[0] = skb->mark; // essential for proxy ingress, see bpf_ipsec.c
return ret;
}
Expand Down Expand Up @@ -1169,9 +1182,8 @@ int tail_ipv4_to_endpoint(struct __sk_buff *skb)
skb->cb[CB_SRC_LABEL] = 0;
ret = ipv4_policy(skb, 0, src_identity, &reason, &proxy_port);

if (proxy_port != 0) {
if (ret == POLICY_ACT_PROXY_REDIRECT)
ret = skb_redirect_to_proxy_hairpin(skb, proxy_port);
}

out:
if (IS_ERR(ret))
Expand Down
3 changes: 3 additions & 0 deletions bpf/lib/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ enum {
*/
#define IPSEC_ENDPOINT TC_ACT_OK

/* Return value to indicate that proxy redirection is required */
#define POLICY_ACT_PROXY_REDIRECT (1 << 16)

/* Cilium error codes, must NOT overlap with TC return codes.
* These also serve as drop reasons for metrics,
* where reason > 0 corresponds to -(DROP_*)
Expand Down
2 changes: 1 addition & 1 deletion daemon/bpf.sha
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
GO_BINDATA_SHA1SUM=b2a1b7f878323fce6afa178a3bc347aa457a923c
GO_BINDATA_SHA1SUM=207cb3f96374de2ae0423c0cb679f19d8aa03b73
BPF_FILES=../bpf/COPYING ../bpf/Makefile ../bpf/Makefile.bpf ../bpf/bpf_alignchecker.c ../bpf/bpf_features.h ../bpf/bpf_hostdev_ingress.c ../bpf/bpf_ipsec.c ../bpf/bpf_lxc.c ../bpf/bpf_netdev.c ../bpf/bpf_network.c ../bpf/bpf_overlay.c ../bpf/bpf_sock.c ../bpf/bpf_xdp.c ../bpf/cilium-map-migrate.c ../bpf/filter_config.h ../bpf/include/bpf/api.h ../bpf/include/elf/elf.h ../bpf/include/elf/gelf.h ../bpf/include/elf/libelf.h ../bpf/include/iproute2/bpf_elf.h ../bpf/include/linux/bpf.h ../bpf/include/linux/bpf_common.h ../bpf/include/linux/byteorder.h ../bpf/include/linux/byteorder/big_endian.h ../bpf/include/linux/byteorder/little_endian.h ../bpf/include/linux/icmp.h ../bpf/include/linux/icmpv6.h ../bpf/include/linux/if_arp.h ../bpf/include/linux/if_ether.h ../bpf/include/linux/if_packet.h ../bpf/include/linux/in.h ../bpf/include/linux/in6.h ../bpf/include/linux/ioctl.h ../bpf/include/linux/ip.h ../bpf/include/linux/ipv6.h ../bpf/include/linux/perf_event.h ../bpf/include/linux/swab.h ../bpf/include/linux/tcp.h ../bpf/include/linux/type_mapper.h ../bpf/include/linux/udp.h ../bpf/init.sh ../bpf/lib/arp.h ../bpf/lib/common.h ../bpf/lib/config.h ../bpf/lib/conntrack.h ../bpf/lib/conntrack_map.h ../bpf/lib/conntrack_test.h ../bpf/lib/csum.h ../bpf/lib/dbg.h ../bpf/lib/drop.h ../bpf/lib/encap.h ../bpf/lib/eps.h ../bpf/lib/eth.h ../bpf/lib/events.h ../bpf/lib/icmp6.h ../bpf/lib/identity.h ../bpf/lib/ipv4.h ../bpf/lib/ipv6.h ../bpf/lib/ipv6_test.h ../bpf/lib/l3.h ../bpf/lib/l4.h ../bpf/lib/lb.h ../bpf/lib/lxc.h ../bpf/lib/maps.h ../bpf/lib/metrics.h ../bpf/lib/nat.h ../bpf/lib/nat46.h ../bpf/lib/nodeport.h ../bpf/lib/policy.h ../bpf/lib/signal.h ../bpf/lib/tailcall.h ../bpf/lib/trace.h ../bpf/lib/utils.h ../bpf/lib/xdp.h ../bpf/lxc_config.h ../bpf/netdev_config.h ../bpf/node_config.h ../bpf/probes/raw_change_tail.t ../bpf/probes/raw_fib_lookup.t ../bpf/probes/raw_insn.h ../bpf/probes/raw_invalidate_hash.t ../bpf/probes/raw_lpm_map.t ../bpf/probes/raw_lru_map.t ../bpf/probes/raw_main.c ../bpf/probes/raw_max_insn.t ../bpf/probes/raw_sock_cookie.t ../bpf/run_probes.sh ../bpf/sockops/Makefile ../bpf/sockops/bpf_redir.c ../bpf/sockops/bpf_sockops.c ../bpf/sockops/bpf_sockops.h ../bpf/sockops/sockops_config.h

0 comments on commit c58d749

Please sign in to comment.