This commit is contained in:
yunwei37
2023-07-28 12:05:53 +00:00
parent 196b6653c5
commit 743c2ea332
24 changed files with 2461 additions and 0 deletions

9
30-openssl/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.vscode
package.json
*.o
*.skel.json
*.skel.yaml
package.yaml
ecli
bootstrap
openssl

141
30-openssl/Makefile Normal file
View File

@@ -0,0 +1,141 @@
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
OUTPUT := .output
CLANG ?= clang
LIBBPF_SRC := $(abspath ../../libbpf/src)
BPFTOOL_SRC := $(abspath ../../bpftool/src)
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool)
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool
LIBBLAZESYM_SRC := $(abspath ../../blazesym/)
LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym.a)
LIBBLAZESYM_HEADER := $(abspath $(OUTPUT)/blazesym.h)
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \
| sed 's/arm.*/arm/' \
| sed 's/aarch64/arm64/' \
| sed 's/ppc64le/powerpc/' \
| sed 's/mips.*/mips/' \
| sed 's/riscv64/riscv/' \
| sed 's/loongarch64/loongarch/')
VMLINUX := ../../vmlinux/$(ARCH)/vmlinux.h
# Use our own libbpf API headers and Linux UAPI headers distributed with
# libbpf to avoid dependency on system-wide headers, which could be missing or
# outdated
INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX))
CFLAGS := -g -Wall
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)
APPS = bootstrap # minimal minimal_legacy uprobe kprobe fentry usdt sockfilter tc ksyscall
CARGO ?= $(shell which cargo)
ifeq ($(strip $(CARGO)),)
BZS_APPS :=
else
BZS_APPS := # profile
APPS += $(BZS_APPS)
# Required by libblazesym
ALL_LDFLAGS += -lrt -ldl -lpthread -lm
endif
# Get Clang's default includes on this system. We'll explicitly add these dirs
# to the includes list when compiling with `-target bpf` because otherwise some
# architecture-specific dirs will be "missing" on some architectures/distros -
# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h,
# sys/cdefs.h etc. might be missing.
#
# Use '-idirafter': Don't interfere with include mechanics except where the
# build would have failed anyways.
CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - </dev/null 2>&1 \
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
ifeq ($(V),1)
Q =
msg =
else
Q = @
msg = @printf ' %-8s %s%s\n' \
"$(1)" \
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \
"$(if $(3), $(3))";
MAKEFLAGS += --no-print-directory
endif
define allow-override
$(if $(or $(findstring environment,$(origin $(1))),\
$(findstring command line,$(origin $(1)))),,\
$(eval $(1) = $(2)))
endef
$(call allow-override,CC,$(CROSS_COMPILE)cc)
$(call allow-override,LD,$(CROSS_COMPILE)ld)
.PHONY: all
all: $(APPS)
.PHONY: clean
clean:
$(call msg,CLEAN)
$(Q)rm -rf $(OUTPUT) $(APPS)
$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT):
$(call msg,MKDIR,$@)
$(Q)mkdir -p $@
# Build libbpf
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf
$(call msg,LIB,$@)
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \
INCLUDEDIR= LIBDIR= UAPIDIR= \
install
# Build bpftool
$(BPFTOOL): | $(BPFTOOL_OUTPUT)
$(call msg,BPFTOOL,$@)
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap
$(LIBBLAZESYM_SRC)/target/release/libblazesym.a::
$(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --features=cheader,dont-generate-test-files --release
$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT)
$(call msg,LIB, $@)
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@
$(LIBBLAZESYM_HEADER): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT)
$(call msg,LIB,$@)
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/blazesym.h $@
# Build BPF code
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL)
$(call msg,BPF,$@)
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \
-c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
$(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
# Generate BPF skeletons
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL)
$(call msg,GEN-SKEL,$@)
$(Q)$(BPFTOOL) gen skeleton $< > $@
# Build user-space code
$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT)
$(call msg,CC,$@)
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@
$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_HEADER)
$(BZS_APPS): $(LIBBLAZESYM_OBJ)
# Build application binary
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT)
$(call msg,BINARY,$@)
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@
# delete failed targets
.DELETE_ON_ERROR:
# keep intermediate (.skel.h, .bpf.o, etc) targets
.SECONDARY:

41
30-openssl/common.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef COMMON_H
#define COMMON_H
#ifdef DEBUG_PRINT
#define debug_bpf_printk(fmt, ...) \
do { \
char s[] = fmt; \
bpf_trace_printk(s, sizeof(s), ##__VA_ARGS__); \
} while (0)
#else
#define debug_bpf_printk(fmt, ...)
#endif
#define TASK_COMM_LEN 16
#define MAX_DATA_SIZE_OPENSSL 1024 * 4
#define MAX_DATA_SIZE_MYSQL 256
#define MAX_DATA_SIZE_POSTGRES 256
#define MAX_DATA_SIZE_BASH 256
// enum_server_command, via
// https://dev.mysql.com/doc/internals/en/com-query.html COM_QUERT command 03
#define COM_QUERY 3
#define AF_INET 2
#define AF_INET6 10
#define SA_DATA_LEN 14
#define BASH_ERRNO_DEFAULT 128
// Optional Target PID
// .rodata section bug via : https://github.com/ehids/ecapture/issues/39
#ifndef KERNEL_LESS_5_2
const volatile u64 target_pid = 0;
const volatile int target_errno = BASH_ERRNO_DEFAULT;
#else
// u64 target_pid = 0;
#endif
char __license[] SEC("license") = "Dual MIT/GPL";
__u32 _version SEC("version") = 0xFFFFFFFE;
#endif

248
30-openssl/openssl.bpf.c Normal file
View File

@@ -0,0 +1,248 @@
#include "openssl_trace.bpf.h"
enum ssl_data_event_type { kSSLRead, kSSLWrite };
const u32 invalidFD = 0;
struct ssl_data_event_t {
enum ssl_data_event_type type;
u64 timestamp_ns;
u32 pid;
u32 tid;
char data[MAX_DATA_SIZE_OPENSSL];
s32 data_len;
char comm[TASK_COMM_LEN];
u32 fd;
};
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
} tls_events SEC(".maps");
struct active_ssl_buf {
u32 fd;
const char* buf;
};
// BPF programs are limited to a 512-byte stack. We store this value per CPU
// and use it as a heap allocated value.
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, u32);
__type(value, struct ssl_data_event_t);
__uint(max_entries, 1);
} data_buffer_heap SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u64);
__type(value, struct active_ssl_buf);
__uint(max_entries, 1024);
} active_ssl_read_args_map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u64);
__type(value, struct active_ssl_buf);
__uint(max_entries, 1024);
} active_ssl_write_args_map SEC(".maps");
// OPENSSL struct to offset , via kern/README.md
typedef long (*unused_fn)();
struct unused {};
struct BIO {
const struct unused* method;
unused_fn callback;
unused_fn callback_ex;
char* cb_arg; /* first argument for the callback */
int init;
int shutdown;
int flags; /* extra storage */
int retry_reason;
int num;
};
struct ssl_st {
int version;
struct unused* method;
struct BIO* rbio; // used by SSL_read
struct BIO* wbio; // used by SSL_write
};
/***********************************************************
* General helper functions
***********************************************************/
static __inline struct ssl_data_event_t* create_ssl_data_event(
u64 current_pid_tgid) {
u32 kZero = 0;
struct ssl_data_event_t* event =
bpf_map_lookup_elem(&data_buffer_heap, &kZero);
if (event == NULL) {
return NULL;
}
const u32 kMask32b = 0xffffffff;
event->timestamp_ns = bpf_ktime_get_ns();
event->pid = current_pid_tgid >> 32;
event->tid = current_pid_tgid & kMask32b;
event->fd = invalidFD;
return event;
}
/***********************************************************
* BPF syscall processing functions
***********************************************************/
static int process_SSL_data(struct pt_regs* ctx, u64 id,
enum ssl_data_event_type type, const char* buf,
u32 fd) {
int len = (int)PT_REGS_RC(ctx);
if (len < 0) {
return 0;
}
struct ssl_data_event_t* event = create_ssl_data_event(id);
if (event == NULL) {
return 0;
}
event->type = type;
event->fd = fd;
// This is a max function, but it is written in such a way to keep older BPF
// verifiers happy.
event->data_len =
(len < MAX_DATA_SIZE_OPENSSL ? (len & (MAX_DATA_SIZE_OPENSSL - 1))
: MAX_DATA_SIZE_OPENSSL);
bpf_probe_read(event->data, event->data_len, buf);
bpf_get_current_comm(&event->comm, sizeof(event->comm));
bpf_perf_event_output(ctx, &tls_events, BPF_F_CURRENT_CPU, event,
sizeof(struct ssl_data_event_t));
return 0;
}
/***********************************************************
* BPF probe function entry-points
***********************************************************/
// Function signature being probed:
// int SSL_write(SSL *ssl, const void *buf, int num);
SEC("uprobe/SSL_write")
int probe_entry_SSL_write(struct pt_regs* ctx) {
u64 current_pid_tgid = bpf_get_current_pid_tgid();
u32 pid = current_pid_tgid >> 32;
#ifndef KERNEL_LESS_5_2
// if target_ppid is 0 then we target all pids
if (target_pid != 0 && target_pid != pid) {
return 0;
}
#endif
// debug_bpf_printk("openssl uprobe/SSL_write pid :%d\n", pid);
void* ssl = (void*)PT_REGS_PARM1(ctx);
// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/bio/bio_local.h
struct ssl_st ssl_info;
bpf_probe_read_user(&ssl_info, sizeof(ssl_info), ssl);
struct BIO bio_w;
bpf_probe_read_user(&bio_w, sizeof(bio_w), ssl_info.wbio);
// get fd ssl->wbio->num
u32 fd = bio_w.num;
// debug_bpf_printk("openssl uprobe SSL_write FD:%d\n", fd);
const char* buf = (const char*)PT_REGS_PARM2(ctx);
struct active_ssl_buf active_ssl_buf_t;
__builtin_memset(&active_ssl_buf_t, 0, sizeof(active_ssl_buf_t));
active_ssl_buf_t.fd = fd;
active_ssl_buf_t.buf = buf;
bpf_map_update_elem(&active_ssl_write_args_map, &current_pid_tgid,
&active_ssl_buf_t, BPF_ANY);
return 0;
}
SEC("uretprobe/SSL_write")
int probe_ret_SSL_write(struct pt_regs* ctx) {
u64 current_pid_tgid = bpf_get_current_pid_tgid();
u32 pid = current_pid_tgid >> 32;
#ifndef KERNEL_LESS_5_2
// if target_ppid is 0 then we target all pids
if (target_pid != 0 && target_pid != pid) {
return 0;
}
#endif
// debug_bpf_printk("openssl uretprobe/SSL_write pid :%d\n", pid);
struct active_ssl_buf* active_ssl_buf_t =
bpf_map_lookup_elem(&active_ssl_write_args_map, &current_pid_tgid);
if (active_ssl_buf_t != NULL) {
const char* buf;
u32 fd = active_ssl_buf_t->fd;
bpf_probe_read(&buf, sizeof(const char*), &active_ssl_buf_t->buf);
process_SSL_data(ctx, current_pid_tgid, kSSLWrite, buf, fd);
}
bpf_map_delete_elem(&active_ssl_write_args_map, &current_pid_tgid);
return 0;
}
// Function signature being probed:
// int SSL_read(SSL *s, void *buf, int num)
SEC("uprobe/SSL_read")
int probe_entry_SSL_read(struct pt_regs* ctx) {
u64 current_pid_tgid = bpf_get_current_pid_tgid();
u32 pid = current_pid_tgid >> 32;
#ifndef KERNEL_LESS_5_2
// if target_ppid is 0 then we target all pids
if (target_pid != 0 && target_pid != pid) {
return 0;
}
#endif
void* ssl = (void*)PT_REGS_PARM1(ctx);
// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/bio/bio_local.h
struct ssl_st ssl_info;
bpf_probe_read_user(&ssl_info, sizeof(ssl_info), ssl);
struct BIO bio_r;
bpf_probe_read_user(&bio_r, sizeof(bio_r), ssl_info.rbio);
// get fd ssl->rbio->num
u32 fd = bio_r.num;
debug_bpf_printk("openssl uprobe PID:%d, SSL_read FD:%d\n", pid, fd);
const char* buf = (const char*)PT_REGS_PARM2(ctx);
struct active_ssl_buf active_ssl_buf_t;
__builtin_memset(&active_ssl_buf_t, 0, sizeof(active_ssl_buf_t));
active_ssl_buf_t.fd = fd;
active_ssl_buf_t.buf = buf;
bpf_map_update_elem(&active_ssl_read_args_map, &current_pid_tgid,
&active_ssl_buf_t, BPF_ANY);
return 0;
}
SEC("uretprobe/SSL_read")
int probe_ret_SSL_read(struct pt_regs* ctx) {
u64 current_pid_tgid = bpf_get_current_pid_tgid();
u32 pid = current_pid_tgid >> 32;
#ifndef KERNEL_LESS_5_2
// if target_ppid is 0 then we target all pids
if (target_pid != 0 && target_pid != pid) {
return 0;
}
#endif
struct active_ssl_buf* active_ssl_buf_t =
bpf_map_lookup_elem(&active_ssl_read_args_map, &current_pid_tgid);
if (active_ssl_buf_t != NULL) {
const char* buf;
u32 fd = active_ssl_buf_t->fd;
bpf_probe_read(&buf, sizeof(const char*), &active_ssl_buf_t->buf);
process_SSL_data(ctx, current_pid_tgid, kSSLRead, buf, fd);
}
bpf_map_delete_elem(&active_ssl_read_args_map, &current_pid_tgid);
return 0;
}

11
30-openssl/openssl.bpf.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef OPENSS_TRACE_BPF_H
#define OPENSS_TRACE_BPF_H
//CO:RE is enabled
#include "headers/vmlinux.h"
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "common.h"
#endif

173
30-openssl/openssl.c Normal file
View File

@@ -0,0 +1,173 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
/* Copyright (c) 2020 Facebook */
#include <argp.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "openssl.h"
#include "openssl.skel.h"
static struct env {
bool verbose;
long min_duration_ms;
} env;
const char *argp_program_version = "openssl 0.0";
const char *argp_program_bug_address = "<bpf@vger.kernel.org>";
const char argp_program_doc[] =
"BPF openssl demo application.\n"
"\n"
"It traces process start and exits and shows associated \n"
"information (filename, process duration, PID and PPID, etc).\n"
"\n"
"USAGE: ./openssl [-d <min-duration-ms>] [-v]\n";
static const struct argp_option opts[] = {
{ "verbose", 'v', NULL, 0, "Verbose debug output" },
{ "duration", 'd', "DURATION-MS", 0, "Minimum process duration (ms) to report" },
{},
};
static error_t parse_arg(int key, char *arg, struct argp_state *state)
{
switch (key) {
case 'v':
env.verbose = true;
break;
case 'd':
errno = 0;
env.min_duration_ms = strtol(arg, NULL, 10);
if (errno || env.min_duration_ms <= 0) {
fprintf(stderr, "Invalid duration: %s\n", arg);
argp_usage(state);
}
break;
case ARGP_KEY_ARG:
argp_usage(state);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static const struct argp argp = {
.options = opts,
.parser = parse_arg,
.doc = argp_program_doc,
};
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
if (level == LIBBPF_DEBUG && !env.verbose)
return 0;
return vfprintf(stderr, format, args);
}
static volatile bool exiting = false;
static void sig_handler(int sig)
{
exiting = true;
}
static int handle_event(void *ctx, void *data, size_t data_sz)
{
const struct event *e = data;
struct tm *tm;
char ts[32];
time_t t;
time(&t);
tm = localtime(&t);
strftime(ts, sizeof(ts), "%H:%M:%S", tm);
if (e->exit_event) {
printf("%-8s %-5s %-16s %-7d %-7d [%u]",
ts, "EXIT", e->comm, e->pid, e->ppid, e->exit_code);
if (e->duration_ns)
printf(" (%llums)", e->duration_ns / 1000000);
printf("\n");
} else {
printf("%-8s %-5s %-16s %-7d %-7d %s\n",
ts, "EXEC", e->comm, e->pid, e->ppid, e->filename);
}
return 0;
}
int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
struct openssl_bpf *skel;
int err;
/* Parse command line arguments */
err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
if (err)
return err;
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Cleaner handling of Ctrl-C */
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
/* Load and verify BPF application */
skel = openssl_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open and load BPF skeleton\n");
return 1;
}
/* Parameterize BPF code with minimum duration parameter */
skel->rodata->min_duration_ns = env.min_duration_ms * 1000000ULL;
/* Load & verify BPF programs */
err = openssl_bpf__load(skel);
if (err) {
fprintf(stderr, "Failed to load and verify BPF skeleton\n");
goto cleanup;
}
/* Attach tracepoints */
err = openssl_bpf__attach(skel);
if (err) {
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto cleanup;
}
/* Set up ring buffer polling */
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
if (!rb) {
err = -1;
fprintf(stderr, "Failed to create ring buffer\n");
goto cleanup;
}
/* Process events */
printf("%-8s %-5s %-16s %-7s %-7s %s\n",
"TIME", "EVENT", "COMM", "PID", "PPID", "FILENAME/EXIT CODE");
while (!exiting) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
/* Ctrl-C will cause -EINTR */
if (err == -EINTR) {
err = 0;
break;
}
if (err < 0) {
printf("Error polling perf buffer: %d\n", err);
break;
}
}
cleanup:
/* Clean up */
ring_buffer__free(rb);
openssl_bpf__destroy(skel);
return err < 0 ? -err : 0;
}

View File

@@ -0,0 +1,9 @@
certs:
openssl req -x509 -nodes -newkey rsa:4096 -keyout client.key -out client.crt -days 365 -subj '/CN=example.com'
openssl req -x509 -nodes -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -subj '/CN=example.com'
clean:
rm -f client.key client.crt
rm -f server.key server.crt

View File

@@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFDTCCAvWgAwIBAgIUelsm684mMQjCCN029zGerL7lN6gwDQYJKoZIhvcNAQEL
BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjIwNTA1MTUxNTQ1WhcNMjMw
NTA1MTUxNTQ1WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAL1PHUhs7Ua78Xf789ZKna+1aNnXJuJ8kzjuv3A1
iLCvs8rJgmhThlnjXQVOsOXVUCHoajW/z6OWf9bMx/MH7z9btXdZFyWF847x37Gy
9qYroppu5grXwIZjQYPK4ZO5K8MDBfRD3M8oWvj9d5aU0/S2ia6jP+A7Az6wf8cl
BBQ32DQA7ySCocbKbaFcikqpaez1nADXg5TdBxf1YsKkYFKj4P9Il3QSByeNcRwY
ZE0x8gK7AGZEEjoUU2+IL2BqEx54yJQDYZ7NZ+5IBl7HkMYByR1PgHUhreWAMPTr
sO8/WrNj10nbJRBZEpsphAnvC5noaQ7SdqMRbr8i2y+LUA6jqtusd8OZsUwNDwD3
g1VZZ9f1QyJ5IgV3SQqEDSFCbOS1ASqMODU7Iubpt170PiCxEUIZbP93VtP+0tuS
noI0lki/61ui+z3yhwNMzkohby+XDY79oZNw8phI5rYJmxjayzrfjGv2p1a37//p
pQiL0YKdcoL9HIe4qu8WKHH324h2RCpUw/SPhG1U4627hv97DQotA1Ee+t5+dh96
GLVacGiRzAASprELHmfJ37/fdb170gncZh3kLaG+TV4hsMhijKjX9CW+bmwehPCe
BUuHvBYkiZVjIl937R34qznW5Cnhvktaj6sC6QU6sI6C3K3odkaCfcGR0Sb9NZ4a
zXq1AgMBAAGjUzBRMB0GA1UdDgQWBBTGX8kbOfG3OivNo2u0i4qb8fe4CjAfBgNV
HSMEGDAWgBTGX8kbOfG3OivNo2u0i4qb8fe4CjAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4ICAQBToRKubwmK3lEKMm5mPP+lQbPO+Y0kW6OXpdAMSLCT
TP+hml/SD5+G86cj/XmxPT2BFUrEOaqfTV7Yk7QyV7Wi15Bd1dqnSINM7HzuD0WF
7MS6tQ3/qErSWmUPhgp+9smxJSsSJDyjkRZnKT0p9c/1f7J4jOhByF+OLbSMVy0c
MTV5iivgBKdZW/IQp03lc/2Tj0zbCePXR26WDiFBJ7fgkWOXZG/FmUkSp2rKNv7v
vGEo9K5nEcYzTuGnO/J5TyYxlMQrJjz2+dfSOfN/Xv9sSAifJG4M7UqcY6UWrKZ+
r4Yd+pVAN5ahNljqC/daekKyLn8fYx1LyAGmgViV1rR53gnStutquMaHiz+UrE7N
3L2UL0lSDGR7vUMa3LuVrAHAk/GKgVRGi4qaprl2GhXpd1mDhiSW48C/C9MZGS3J
2Nwmu5hBuGdBtVhSU7rYNiU3rMxPwPcy6PgJIo4xlaKDzSvy2cSqiKND3yh9WfmV
s+xXlQG+6xr5+eiQDe3o0/li006jTv1Ypql/nf/ma5qQrhe2DsZl1WGOxo1sOpJo
IAVCIuTMnxSxvPfL9Ux47J7hA5/ovumRwiyApbOncw8/I66geHwTKG2kt3Mni53h
qP7Q2II7NqEU4BfWMUsgJAOLbXvLtwdP5+naY52GvEAK9KgipHVeSKUKASLDxzC8
NA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
YJBwHSU2XT8UgdxJka4Kou0tlNpmhw==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python
# Copyright 2018- The Pixie Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
import socket
import ssl
import time
import random
host_addr = '127.0.0.1'
host_port = 8082
server_sni_hostname = 'example.com'
client_cert = 'client.crt'
client_key = 'client.key'
server_cert = 'server.crt'
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=server_cert)
context.load_cert_chain(certfile=client_cert, keyfile=client_key)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn = context.wrap_socket(s, server_side=False, server_hostname=server_sni_hostname)
conn.connect((host_addr, host_port))
print("SSL established.")
count = 0
while True:
time.sleep(1)
secret = random.randint(0, 1024 * 1024 * 1024)
conn.send("Client secret {} is {}".format(count, secret).encode())
data = conn.recv(1024)
print(data.decode())
count += 1
print("Closing connection")
conn.close()

View File

@@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFDTCCAvWgAwIBAgIUYR+ByE3MsNfeQxOwoD6Qdn5NQlIwDQYJKoZIhvcNAQEL
BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjIwNTA1MTUxNTQ2WhcNMjMw
NTA1MTUxNTQ2WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAJbRQViOAWLIz8pue5lT09OYpvbHsp9wpjo+yUbE
zOzCJwraBDUEaiGVokjWiqMBkZP8fJKu5lt1guTwStPJRj66ZK/GmxGN27OhXGT9
M1mBTH42cFyld/17Wny0MX4HOl1jZFT/HYxJDc58SNAXWRUQAL8ihq0NFQS4yqfR
OkxAna/PsvfVj2CkW0vxF6/iUJ3wHJ8pBHXdNu26awM72Ih3zgpF3AICKAyYid8v
2vXTOyzi9Ay5sQPnhmuiysdC/YoYd9ocDSw20HyXfn6lSrZ7LIaw8miRGIug+O+y
BoIxjqAv5u6pDckkzmcsjuWc8xIcXIu/BzBKpWDmdn/rZxA2OElp9y1P98BcTmNR
yYYWyeKWxMPwa3Wdb5rJpb4OlJ+5grDS7bAZwwwm4RfRAJif62RwnToxzd/+GcMP
aJ+E2/T/hIlv5Sp51QdTrLZl3etGxygEkw9Kcdt7YH/4MD77OVNYPla2PHIHPcLH
oqBfDia0b2gQJVRQFEzMsTka9EYNuhqwHyPjVFoGJC6R4PJxceFC6rJ2n3f9i9Tz
R4Wm0i4fi4Mt91Kn2AEclRo4mpVoUy9gbxYYOMw6AlGt+DrKjawMFJ6gOH1ueBaI
Tz92NGQzqwOcTf8YeL2YwoDNGNrIfems76/A5PFWCTH+DA+raQgtgTguopKTYkcu
1xdzAgMBAAGjUzBRMB0GA1UdDgQWBBTuryJv3wC6IefOQGPvCIRjamrAPDAfBgNV
HSMEGDAWgBTuryJv3wC6IefOQGPvCIRjamrAPDAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4ICAQAbXdXeM1cqdJBipS0tRw0fl5GxFjY5wYtu81+Ga4Rm
oQhzG58c1qpx6uqXEq2OBc+tF/ypN+EF5XIyOB5i08TZ/feyiB6/bRPXkB6tleog
KOFS2OZb7/R+CdRAkx/nrWs7M4ZK9Ucxn+XqVDZG+LM1SGOuScE2J8x57BfQxUEC
Yu8sOOwO+0+2fjLeUa7FpOxrX6WUGRwOlm4mWeKaevDD20hZ3gTa4s3AiNPhA2Si
MpuPtVzQbC2WGiFpXSBrvKUhH5IkXepRKSmPaddPUNs6ROqENO9wklo+ttfOzuAL
b8xmSPui+UlivnqFfDEzWAdMv3FJ2rZR+vKPkxCg3WQd8jhs9lR5E1AoIS5CECd2
qmIy8zKb10J0z4ZN9laSppPZ2ktkqbQqs4lSFVgaUUDvvBAlFtorN3fOce7D+PG+
v51sPiHRrnMSvSHpcwyOAWSxw3B+3oOId0UtD4LLXKIXROL0ibT/Iy+xigpgDk32
8aU7kcrviMRrWvnVhT32r6xIVjgfyB+GRO7xKd0kcsWRWSO1Xf28lJKHXLQJ11b+
6HC8ix/8bDue9YDZ37Au7/DGInza+Y6YzlpM6qGAo290A0BjoV5I4P2QZeElSGaa
1GMPCz119ftHdueEXzXhXHnbI0QdinOI9rYC8SsBfIVoDX3OsKGm2FHGAW7ZxMeo
vA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCW0UFYjgFiyM/K
bnuZU9PTmKb2x7KfcKY6PslGxMzswicK2gQ1BGohlaJI1oqjAZGT/HySruZbdYLk
8ErTyUY+umSvxpsRjduzoVxk/TNZgUx+NnBcpXf9e1p8tDF+BzpdY2RU/x2MSQ3O
fEjQF1kVEAC/IoatDRUEuMqn0TpMQJ2vz7L31Y9gpFtL8Rev4lCd8ByfKQR13Tbt
umsDO9iId84KRdwCAigMmInfL9r10zss4vQMubED54ZrosrHQv2KGHfaHA0sNtB8
l35+pUq2eyyGsPJokRiLoPjvsgaCMY6gL+buqQ3JJM5nLI7lnPMSHFyLvwcwSqVg
5nZ/62cQNjhJafctT/fAXE5jUcmGFsnilsTD8Gt1nW+ayaW+DpSfuYKw0u2wGcMM
JuEX0QCYn+tkcJ06Mc3f/hnDD2ifhNv0/4SJb+UqedUHU6y2Zd3rRscoBJMPSnHb
e2B/+DA++zlTWD5WtjxyBz3Cx6KgXw4mtG9oECVUUBRMzLE5GvRGDboasB8j41Ra
BiQukeDycXHhQuqydp93/YvU80eFptIuH4uDLfdSp9gBHJUaOJqVaFMvYG8WGDjM
OgJRrfg6yo2sDBSeoDh9bngWiE8/djRkM6sDnE3/GHi9mMKAzRjayH3prO+vwOTx
Vgkx/gwPq2kILYE4LqKSk2JHLtcXcwIDAQABAoICACRJ21hMauby/JRvuwuskOZz
75CngkI837JaEyIVDl3VZYGF7cc39bV5BKBUBu2r3fRmpy7AKKtO/hzJ+Kc24dEM
Flf5CKzTnk59f/bIucdKhjZEMQsJwXJbcO1aiiIR6Sg5VxXggKKVnV3Wp8pyI7we
qp9S1mbjI/CL6i8w978LOSXpat2ZJDOTuGfwbcujP9SQxsJBI1Kc1K+k0ETp7HMB
qLDuGD7fd/V36oyqPhwyJCXrwd8h+wa+eaiCdho18z18H7J6V20RD187MHOWoACC
aLdL8jfY2bgXFm7OPiSree7vN7irMqb4VTWcEhILjq0H5/i0ES28eEh1i4PCB30P
dvbGHsSmBt2/V+t9+n+1uwji3Riq78bujeBgkE7kz87gTBv59bwCiVCIYDSDiOEw
++mGtIaU40sflEz6JlSddxgmrlh8kZgWWHnGmVNUO6pefAbm8a4mTFGZQtaVtF3G
2HGdYLMdsIeHeFtjbm5ycax8BLq1Q9w8BOyY1GdKtgNnhcPB0uYoo3zCTiUk/G9t
ezpidYBm0h42j6WyGfUUZOULoPRwTg2TbtQrEa/6ZiGwZTEprhKF7MRaaR+EZJ9B
CtyNotFhwkSLSzL1giCINzsuo1mGZpj8BaIbx+FJ+XViVM3KCZphUJnEH3kewnTH
Im69kYe8UT+JJtjUv2XRAoIBAQDNmaZgIXucuQ/HXjR40f/yVi0BCL0utyK98/UC
Kzk5z31F60YrZmyR8SDmzek3HlSWuaYlYO+YAJnKIvho4YJDNWwtLRICGPEeazAM
18Y+QlCRmb6Op54z4x+MXPrajOy7JYjeUCARsahVCcPXXXP9rGAqchOAcO+/KkeP
JWvRF25j6cndPg0bAr8Wjq/yHWVKhiI7O/S9pWdIS2TND5f1xTXHb66WHOKD6K+6
II/h0zX1rIpU2H7sriELHrdXIZQ9S4m2rofAjM8EcTQuB+QegCoqpBF06eo+/EOV
mEirQVKWHaNIL+wuoG6gK43BTKWXinLeK2phHFtC/jFHCajJAoIBAQC7ybw7mb6L
fqgrQf2gY+TArfsR2LyEKzn69GZoxbWIR0prOyLMxlW5krelbjGb01nO9buWxfRO
7k+e+WV0SyoeDaEH3+XGgEkCDN1Y3dXxf6vhmr6HffjGg7JH8EjkxQxsOzNWSntO
0Gnher9iZp5AGXgAh5IOqh/lhnHq2R/SgKU/MyVnSIjmx7yDDwSWjLBNAyiK1459
05bXed8EmkooLdJEG6Jw4f0tQ1ZancqLaK0e7qKYkFZD2yd8qQfIde6OhdJjLP4j
rqGMI7Zcuo4quO2fRIlZRveJU7nneCB/Tq/DbV/JZVkPE++delT2BXkmVz09BLVO
wA/CtRAdy1hbAoIBAEMPWrUANtFniz37/CFsXY8tjIBJ2WrjUPGkIMYUUxYIF1Q2
6Sw+vCrd+11MzESuH+kJpKeMdpmdmIvV3DBZXaOOSTpy+Oy2Ne82BvYpav/joWPc
QctF4NQLwL6HlUqzrINeOsZIXC1pRP53sOkOEkcrcjJmAvZh39D6eVy3V/NbMSZl
mvIOyzeELc+turW94Mvt9Dxd0fYJfSaXcMlxzJ7dNC1YwBk2UquzuZ18AXIm8fKv
1G7YLo4EPcLiweopibB0cvai9qRXSS6pvdtFt6I7K4W8/fSkV0M0BNdGVG2HYOiV
wixJdT/AFFUp35Ks7VYAUncksg36scmoH2qMPAECggEAaesmjaNxMzMUXZnSGXZe
n0NCmtVZt16+TEsvvCbP9nbnhcYMId44mfwkM14NAyxZun8l+Kvc2exW4n8e91Iy
BlN/oXZrHuRayZpB+w7czmNJqm1iy/+Eo0vC8gqYwthV4nIdya0nEdRB9FkMu87P
sa3r3riY7EaOySJk/KbM6SmAiz4o+bGS7kB4lp+Q4e2mvzlp064zg8sliJIH9Yul
CjaWI65GmE8PQ0l42pGnnaxEAW9uLIk07v8crZaVej7yeFcIzMGi8rNcETRPdswO
xhAajzvUEJQTqNSdxe4evk++mYcGgQz2B6gh/fvzEfUSWUrZkqImNa3k9di0p2l7
gwKCAQBq22V0Si7MmVVxMFMrWd2T5wMknYqHxYD2oHTHHxJL92FMT8OB5VF8jder
VUb8YH76g9iWW/xhWtqAx2o1G4Ylb1c6SI7bCCrH8XmAMspJ6o3mVxXuTDz/UrHn
DnfrvRlzjKq8HYWv0yUVo1VYyV8RDnwekFjX9QYmq+LodMePAoATC7vEFI7eG6vd
FsLQsghYQTpg/XRlpdlw3yvmP7BlpexMbX8/vf6Nc8lBWNjZ6zDq4g71hJqI0tim
lrqmEmdhLgAS87hr4t1NsmVwXmhh7BXmbN/1g8Y8FyKOGvNZhJ2/86iNghecAxo9
OldWF5Wk+mFkrEGSlxf7RYw3fFly
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,57 @@
#!/usr/bin/env python
# Copyright 2018- The Pixie Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
import socket
import ssl
import time
import random
listen_addr = '127.0.0.1'
listen_port = 8082
server_cert = 'server.crt'
server_key = 'server.key'
client_certs = 'client.crt'
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile=server_cert, keyfile=server_key)
context.load_verify_locations(cafile=client_certs)
bindsocket = socket.socket()
bindsocket.bind((listen_addr, listen_port))
bindsocket.listen(5)
while True:
print("Waiting for client")
newsocket, fromaddr = bindsocket.accept()
print("Client connected: {}:{}".format(fromaddr[0], fromaddr[1]))
conn = context.wrap_socket(newsocket, server_side=True)
print("SSL established.")
count = 0
while True:
time.sleep(1)
data = conn.recv(1024)
print(data.decode())
secret = random.randint(0, 1024 * 1024 * 1024)
conn.send("Server secret {} is {}".format(count, secret).encode())
count += 1
print("Closing connection")
conn.shutdown(socket.SHUT_RDWR)
conn.close()