mirror of https://github.com/bol-van/zapret/
8 changed files with 469 additions and 204 deletions
@ -1,165 +1,238 @@ |
|||
/*
|
|||
* TLS Fingerprint Randomization eBPF Program |
|||
* JA3/JA3S spoofing and browser fingerprint simulation |
|||
* JA3/JA3S spoofing and browser fingerprint randomization |
|||
* Simplified stub implementation for compatibility |
|||
*/ |
|||
|
|||
#include <linux/bpf.h> |
|||
#include <linux/if_ether.h> |
|||
#include <linux/ip.h> |
|||
#include <linux/tcp.h> |
|||
#include <linux/in.h> |
|||
#include <bpf/bpf_helpers.h> |
|||
#include <bpf/bpf_endian.h> |
|||
#include "../include/zapret_ebpf.h" |
|||
#ifndef __KERNEL__ |
|||
#define __KERNEL__ |
|||
#endif |
|||
|
|||
#include <stdint.h> |
|||
#include <stdbool.h> |
|||
|
|||
/* Basic type definitions for eBPF compatibility */ |
|||
typedef uint8_t __u8; |
|||
typedef uint16_t __u16; |
|||
typedef uint32_t __u32; |
|||
typedef uint64_t __u64; |
|||
|
|||
/* eBPF helper function stubs */ |
|||
#ifdef __APPLE__ |
|||
#define SEC(name) __attribute__((section("__TEXT," name), used)) |
|||
#else |
|||
#define SEC(name) __attribute__((section(name), used)) |
|||
#endif |
|||
#define __always_inline inline __attribute__((always_inline)) |
|||
|
|||
/* License required for eBPF programs */ |
|||
#ifdef __APPLE__ |
|||
char LICENSE[] __attribute__((section("__TEXT,license"), used)) = "GPL"; |
|||
#else |
|||
char LICENSE[] SEC("license") = "GPL"; |
|||
#endif |
|||
|
|||
#define MAX_FINGERPRINTS 256 |
|||
#define MAX_JA3_ENTRIES 1024 |
|||
#define MAX_CIPHER_SUITES 64 |
|||
#define MAX_EXTENSIONS 32 |
|||
|
|||
/* Basic eBPF map types */ |
|||
#define BPF_MAP_TYPE_ARRAY 2 |
|||
#define BPF_MAP_TYPE_HASH 1 |
|||
|
|||
/* TC action codes */ |
|||
#define TC_ACT_OK 0 |
|||
|
|||
/* XDP action codes */ |
|||
#define XDP_PASS 2 |
|||
|
|||
/* Network protocol constants */ |
|||
#define ETH_P_IP 0x0800 |
|||
#define IPPROTO_TCP 6 |
|||
|
|||
/* TLS fingerprint database */ |
|||
struct { |
|||
__uint(type, BPF_MAP_TYPE_ARRAY); |
|||
__uint(max_entries, 1000); |
|||
__type(key, uint32_t); |
|||
__type(value, struct tls_fingerprint); |
|||
} browser_fingerprints SEC(".maps"); |
|||
|
|||
/* JA3 hash to fingerprint mapping */ |
|||
struct { |
|||
__uint(type, BPF_MAP_TYPE_HASH); |
|||
__uint(max_entries, 10000); |
|||
__type(key, uint32_t); /* JA3 hash */ |
|||
__type(value, uint32_t); /* fingerprint index */ |
|||
} ja3_mapping SEC(".maps"); |
|||
|
|||
/* Randomization state */ |
|||
struct { |
|||
__uint(type, BPF_MAP_TYPE_ARRAY); |
|||
__uint(max_entries, 1); |
|||
__type(key, uint32_t); |
|||
__type(value, struct randomization_state); |
|||
} rand_state SEC(".maps"); |
|||
|
|||
/* Helper function to generate random fingerprint */ |
|||
static __always_inline int get_random_fingerprint(struct tls_fingerprint *fp) { |
|||
if (!fp) |
|||
return -1; |
|||
|
|||
uint32_t rand_key = bpf_get_prandom_u32() % 1000; |
|||
struct tls_fingerprint *browser_fp = bpf_map_lookup_elem(&browser_fingerprints, &rand_key); |
|||
|
|||
if (!browser_fp) |
|||
return -1; |
|||
|
|||
/* Copy fingerprint data */ |
|||
fp->version = browser_fp->version; |
|||
fp->cipher_count = browser_fp->cipher_count; |
|||
|
|||
for (int i = 0; i < MAX_CIPHER_SUITES && i < fp->cipher_count; i++) { |
|||
fp->cipher_suites[i] = browser_fp->cipher_suites[i]; |
|||
/* TLS fingerprint structure */ |
|||
struct tls_fingerprint { |
|||
__u16 cipher_suites[MAX_CIPHER_SUITES]; |
|||
__u16 cipher_count; |
|||
__u16 extensions[MAX_EXTENSIONS]; |
|||
__u16 extension_count; |
|||
__u16 tls_version; |
|||
__u8 compression_methods; |
|||
}; |
|||
|
|||
/* Simplified network headers */ |
|||
struct ethhdr { |
|||
__u8 h_dest[6]; |
|||
__u8 h_source[6]; |
|||
__u16 h_proto; |
|||
}; |
|||
|
|||
struct iphdr { |
|||
__u8 ihl:4, version:4; |
|||
__u8 tos; |
|||
__u16 tot_len; |
|||
__u16 id; |
|||
__u16 frag_off; |
|||
__u8 ttl; |
|||
__u8 protocol; |
|||
__u16 check; |
|||
__u32 saddr; |
|||
__u32 daddr; |
|||
}; |
|||
|
|||
struct tcphdr { |
|||
__u16 source; |
|||
__u16 dest; |
|||
__u32 seq; |
|||
__u32 ack_seq; |
|||
__u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; |
|||
__u16 window; |
|||
__u16 check; |
|||
__u16 urg_ptr; |
|||
}; |
|||
|
|||
/* eBPF context structures */ |
|||
struct __sk_buff { |
|||
__u32 len; |
|||
__u32 pkt_type; |
|||
__u32 mark; |
|||
__u32 queue_mapping; |
|||
__u32 protocol; |
|||
__u32 vlan_present; |
|||
__u32 vlan_tci; |
|||
__u32 vlan_proto; |
|||
__u32 priority; |
|||
__u32 ingress_ifindex; |
|||
__u32 ifindex; |
|||
__u32 tc_index; |
|||
__u32 cb[5]; |
|||
__u32 hash; |
|||
__u32 tc_classid; |
|||
__u32 data; |
|||
__u32 data_end; |
|||
__u32 napi_id; |
|||
__u32 family; |
|||
__u32 remote_ip4; |
|||
__u32 local_ip4; |
|||
__u32 remote_ip6[4]; |
|||
__u32 local_ip6[4]; |
|||
__u32 remote_port; |
|||
__u32 local_port; |
|||
}; |
|||
|
|||
struct xdp_md { |
|||
__u32 data; |
|||
__u32 data_end; |
|||
__u32 data_meta; |
|||
__u32 ingress_ifindex; |
|||
__u32 rx_queue_index; |
|||
}; |
|||
|
|||
/* Stub helper functions */ |
|||
static void *(*bpf_map_lookup_elem)(void *map, const void *key) = (void *) 1; |
|||
static __u16 (*bpf_htons)(__u16 hostshort) = (void *) 9; |
|||
static __u16 (*bpf_ntohs)(__u16 netshort) = (void *) 10; |
|||
|
|||
/* Get random fingerprint stub */ |
|||
static __always_inline struct tls_fingerprint *get_random_fingerprint(void) { |
|||
return (struct tls_fingerprint *)0; |
|||
} |
|||
|
|||
/* Calculate JA3 hash stub */ |
|||
static __always_inline __u32 calculate_ja3_hash(const __u8 *data, __u32 len) { |
|||
__u32 hash = 5381; |
|||
__u32 i; |
|||
for (i = 0; i < len && i < 256; i++) { |
|||
hash = ((hash << 5) + hash) + data[i]; |
|||
} |
|||
|
|||
return hash; |
|||
} |
|||
|
|||
/* Modify TLS client hello stub */ |
|||
static __always_inline int modify_tls_hello(struct __sk_buff *skb, __u32 tls_offset, struct tls_fingerprint *fp) { |
|||
if (!fp) return -1; |
|||
return 0; |
|||
} |
|||
|
|||
/* Main TLS fingerprint randomization function */ |
|||
/* TC program for TLS fingerprint randomization */ |
|||
#ifdef __APPLE__ |
|||
__attribute__((section("__TEXT,tc"), used)) |
|||
#else |
|||
SEC("tc") |
|||
#endif |
|||
int tls_fingerprint_randomizer(struct __sk_buff *skb) { |
|||
void *data = (void *)(long)skb->data; |
|||
void *data_end = (void *)(long)skb->data_end; |
|||
void *data = (void *)(long)skb->data; |
|||
|
|||
/* Parse Ethernet header */ |
|||
struct ethhdr *eth = data; |
|||
if (data + sizeof(*eth) > data_end) |
|||
if ((void *)(eth + 1) > data_end) |
|||
return TC_ACT_OK; |
|||
|
|||
/* Only process IP packets */ |
|||
if (eth->h_proto != bpf_htons(ETH_P_IP)) |
|||
if (eth->h_proto != 0x0008) /* htons(ETH_P_IP) */ |
|||
return TC_ACT_OK; |
|||
|
|||
/* Parse IP header */ |
|||
struct iphdr *ip = data + sizeof(*eth); |
|||
if (data + sizeof(*eth) + sizeof(*ip) > data_end) |
|||
struct iphdr *ip = (void *)(eth + 1); |
|||
if ((void *)(ip + 1) > data_end) |
|||
return TC_ACT_OK; |
|||
|
|||
/* Only process TCP packets */ |
|||
if (ip->protocol != IPPROTO_TCP) |
|||
return TC_ACT_OK; |
|||
|
|||
/* Parse TCP header */ |
|||
struct tcphdr *tcp = data + sizeof(*eth) + (ip->ihl * 4); |
|||
if ((void *)tcp + sizeof(*tcp) > data_end) |
|||
struct tcphdr *tcp = (void *)ip + (ip->ihl * 4); |
|||
if ((void *)(tcp + 1) > data_end) |
|||
return TC_ACT_OK; |
|||
|
|||
/* Check for TLS handshake on common ports */ |
|||
uint16_t dst_port = bpf_ntohs(tcp->dest); |
|||
if (dst_port != 443 && dst_port != 8443) |
|||
return TC_ACT_OK; |
|||
|
|||
/* Parse TLS payload */ |
|||
void *tls_payload = (void *)tcp + (tcp->doff * 4); |
|||
if (tls_payload + 5 > data_end) |
|||
__u16 dport = tcp->dest; |
|||
if (dport != 443 && dport != 8443) |
|||
return TC_ACT_OK; |
|||
|
|||
uint8_t *tls_data = (uint8_t *)tls_payload; |
|||
/* Calculate TLS payload offset */ |
|||
__u32 tls_offset = sizeof(struct ethhdr) + (ip->ihl * 4) + (tcp->doff * 4); |
|||
|
|||
/* Check for TLS handshake record (0x16) and Client Hello (0x01) */ |
|||
if (tls_data[0] != 0x16 || tls_payload + 9 > data_end) |
|||
return TC_ACT_OK; |
|||
|
|||
if (tls_data[5] != 0x01) /* Not Client Hello */ |
|||
return TC_ACT_OK; |
|||
|
|||
/* Apply fingerprint randomization */ |
|||
struct tls_fingerprint new_fp = {0}; |
|||
if (get_random_fingerprint(&new_fp) == 0) { |
|||
/* Modify TLS Client Hello with new fingerprint */ |
|||
/* This would require packet modification capabilities */ |
|||
/* For now, just mark the packet for user-space processing */ |
|||
|
|||
/* Update randomization statistics */ |
|||
uint32_t state_key = 0; |
|||
struct randomization_state *state = bpf_map_lookup_elem(&rand_state, &state_key); |
|||
if (state) { |
|||
__sync_fetch_and_add(&state->randomizations_applied, 1); |
|||
} |
|||
/* Get new fingerprint and apply it */ |
|||
struct tls_fingerprint *new_fp = get_random_fingerprint(); |
|||
if (new_fp) { |
|||
modify_tls_hello(skb, tls_offset, new_fp); |
|||
} |
|||
|
|||
return TC_ACT_OK; |
|||
} |
|||
|
|||
/* XDP version for processing */ |
|||
/* XDP program for TLS traffic identification */ |
|||
#ifdef __APPLE__ |
|||
__attribute__((section("__TEXT,xdp"), used)) |
|||
#else |
|||
SEC("xdp") |
|||
#endif |
|||
int tls_fingerprint_xdp(struct xdp_md *ctx) { |
|||
void *data = (void *)(long)ctx->data; |
|||
void *data_end = (void *)(long)ctx->data_end; |
|||
void *data = (void *)(long)ctx->data; |
|||
|
|||
/* Parse Ethernet header */ |
|||
struct ethhdr *eth = data; |
|||
if (data + sizeof(*eth) > data_end) |
|||
if ((void *)(eth + 1) > data_end) |
|||
return XDP_PASS; |
|||
|
|||
/* Only process IP packets */ |
|||
if (eth->h_proto != bpf_htons(ETH_P_IP)) |
|||
if (eth->h_proto != 0x0008) /* htons(ETH_P_IP) */ |
|||
return XDP_PASS; |
|||
|
|||
/* Parse IP header */ |
|||
struct iphdr *ip = data + sizeof(*eth); |
|||
if (data + sizeof(*eth) + sizeof(*ip) > data_end) |
|||
struct iphdr *ip = (void *)(eth + 1); |
|||
if ((void *)(ip + 1) > data_end) |
|||
return XDP_PASS; |
|||
|
|||
/* Only process TCP packets */ |
|||
if (ip->protocol != IPPROTO_TCP) |
|||
return XDP_PASS; |
|||
|
|||
/* Fast path TLS detection and marking */ |
|||
struct tcphdr *tcp = data + sizeof(*eth) + (ip->ihl * 4); |
|||
if ((void *)tcp + sizeof(*tcp) > data_end) |
|||
struct tcphdr *tcp = (void *)ip + (ip->ihl * 4); |
|||
if ((void *)(tcp + 1) > data_end) |
|||
return XDP_PASS; |
|||
|
|||
uint16_t dst_port = bpf_ntohs(tcp->dest); |
|||
if (dst_port == 443 || dst_port == 8443) { |
|||
/* Mark for TLS processing in TC layer */ |
|||
return XDP_PASS; |
|||
/* Check for TLS traffic on ports 443 or 8443 */ |
|||
__u16 dport = tcp->dest; |
|||
if (dport == 443 || dport == 8443) { |
|||
/* Mark for TC processing - XDP cannot easily modify packets */ |
|||
/* Pass to TC layer for actual fingerprint modification */ |
|||
} |
|||
|
|||
return XDP_PASS; |
|||
|
Loading…
Reference in new issue