Skip to content

Commit

Permalink
xdp-sni: change lpm trie map to hash map
Browse files Browse the repository at this point in the history
switch LPM trie map to hash map to reduce code complexity
so we can drop reverse_string to avoid verifier error.
it will be less convienent though since now we need to
add each domain and it's subdomain to hash map to block
the domain and subdomain site.

Signed-off-by: Vincent Li <[email protected]>
  • Loading branch information
vincentmli committed Oct 9, 2024
1 parent 0bf620f commit afc1a9c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 65 deletions.
55 changes: 17 additions & 38 deletions xdp-sni/xdp_sni.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,13 @@
#define SERVER_NAME_EXTENSION 0
#define MAX_DOMAIN_SIZE 63

struct domain_name {
struct bpf_lpm_trie_key lpm_key;
char server_name[MAX_DOMAIN_SIZE + 1];
};

struct {
__uint(type, BPF_MAP_TYPE_LPM_TRIE);
__type(key, struct domain_name);
__type(value, __u8);
__uint(max_entries, 10000);
__uint(pinning, LIBBPF_PIN_BY_NAME);
__uint(map_flags, BPF_F_NO_PREALLOC);
__uint(type, BPF_MAP_TYPE_HASH); // Hash map for SNI denylist
__type(key, char[MAX_DOMAIN_SIZE + 1]); // Server name as the key
__type(value, __u8); // Value could be anything (e.g., 1 for blacklisted)
__uint(max_entries, 10000);
__uint(pinning, LIBBPF_PIN_BY_NAME);
__uint(map_flags, BPF_F_NO_PREALLOC);
} sni_denylist SEC(".maps");

struct extension {
Expand Down Expand Up @@ -197,50 +192,35 @@ int xdp_tls_sni(struct xdp_md *ctx)

if (ext->type == SERVER_NAME_EXTENSION) {
// Allocate a buffer from the ring buffer
struct sni_event *event = bpf_ringbuf_reserve(
&sni_ringbuf, sizeof(*event), 0);
struct sni_event *event = bpf_ringbuf_reserve( &sni_ringbuf, sizeof(*event), 0);
if (!event)
goto end; // Drop if no space

struct domain_name dn = { 0 };
char server_name[MAX_DOMAIN_SIZE + 1] = {0}; // Allocate server name buffer

if (data_end <
(cursor + sizeof(struct sni_extension))) {
if (data_end < (cursor + sizeof(struct sni_extension))) {
bpf_ringbuf_discard(event, 0);
goto end;
}

struct sni_extension *sni =
(struct sni_extension *)cursor;
struct sni_extension *sni = (struct sni_extension *)cursor;

cursor += sizeof(struct sni_extension);

__u16 server_name_len = bpf_ntohs(sni->len);

//avoid invalid write to stack R1 off=0 size=1
if (server_name_len >= sizeof(dn.server_name)) {
if (server_name_len >= sizeof(server_name)) {
bpf_ringbuf_discard(event, 0);
goto end;
}

for (int sn_idx = 0; sn_idx < server_name_len;
sn_idx++) {
// invalid access to packet, off=11 size=1, R5(id=0,off=11,r=11)
// R5 offset is outside of the packet
for (int sn_idx = 0; sn_idx < server_name_len; sn_idx++) {
if (data_end < cursor + sn_idx + 1) {
bpf_ringbuf_discard(event, 0);
goto end;
}

if (dn.server_name +
sizeof(struct domain_name) <
dn.server_name + sn_idx) {
bpf_ringbuf_discard(event, 0);
goto end;
}

dn.server_name[sn_idx] =
((char *)cursor)[sn_idx];
server_name[sn_idx] = ((char *)cursor)[sn_idx];
event->sni[sn_idx] = ((char *)cursor)[sn_idx];
}

Expand All @@ -250,15 +230,14 @@ int xdp_tls_sni(struct xdp_md *ctx)

bpf_ringbuf_submit(event, 0);

dn.server_name[MAX_DOMAIN_SIZE] = '\0';
dn.lpm_key.prefixlen = server_name_len * 8;
server_name[MAX_DOMAIN_SIZE] = '\0';

bpf_printk("TLS SNI: %s", dn.server_name);
bpf_printk("TLS SNI: %s", server_name);

if (bpf_map_lookup_elem(&sni_denylist, &dn)) {
if (bpf_map_lookup_elem(&sni_denylist, &server_name)) {
bpf_printk(
"Domain %s found in denylist, dropping packet\n",
dn.server_name);
server_name);
return XDP_DROP;
}

Expand Down
34 changes: 7 additions & 27 deletions xdp-sni/xdp_sni.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,10 @@

#define MAX_DOMAIN_SIZE 63

struct domain_name {
struct bpf_lpm_trie_key lpm_key;
char server_name[MAX_DOMAIN_SIZE + 1];
};

// Function to reverse the entire domain string, including the dot
static void reverse_string(char *str)
{
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}

int main(int argc, char *argv[])
{
int map_fd;
struct domain_name dn = { 0 };
char server_name[MAX_DOMAIN_SIZE + 1] = {0};
__u8 value = 1;

// Check for proper number of arguments
Expand All @@ -53,12 +37,8 @@ int main(int argc, char *argv[])
}

// Reverse the input domain
strncpy(dn.server_name, argv[2], MAX_DOMAIN_SIZE);
dn.server_name[MAX_DOMAIN_SIZE] = '\0'; // Ensure null termination
reverse_string(dn.server_name);

// Set the LPM trie key prefix length
dn.lpm_key.prefixlen = strlen(dn.server_name) * 8;
strncpy(server_name, argv[2], MAX_DOMAIN_SIZE);
server_name[MAX_DOMAIN_SIZE] = '\0'; // Ensure null termination

// Open the BPF map
map_fd = bpf_obj_get("/sys/fs/bpf/xdp-sni/sni_denylist");
Expand All @@ -70,23 +50,23 @@ int main(int argc, char *argv[])
// Add or delete the domain based on the first argument
if (strcmp(argv[1], "add") == 0) {
// Update the map with the reversed domain name
if (bpf_map_update_elem(map_fd, &dn, &value, BPF_ANY) != 0) {
if (bpf_map_update_elem(map_fd, server_name, &value, BPF_ANY) != 0) {
fprintf(stderr, "Failed to add domain to map: %s\n",
strerror(errno));
return 1;
}
printf("Domain %s (reversed: %s) added to denylist\n", argv[2],
dn.server_name);
server_name);
} else if (strcmp(argv[1], "delete") == 0) {
// Remove the reversed domain from the map
if (bpf_map_delete_elem(map_fd, &dn) != 0) {
if (bpf_map_delete_elem(map_fd, server_name) != 0) {
fprintf(stderr,
"Failed to remove domain from map: %s\n",
strerror(errno));
return 1;
}
printf("Domain %s (reversed: %s) removed from denylist\n",
argv[2], dn.server_name);
argv[2], server_name);
} else {
fprintf(stderr, "Invalid command: %s. Use 'add' or 'delete'.\n",
argv[1]);
Expand Down

0 comments on commit afc1a9c

Please sign in to comment.