Skip to content

Instantly share code, notes, and snippets.

@jpbland1
Last active December 15, 2022 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpbland1/ad46617fcc40934b252ce031c7aa5969 to your computer and use it in GitHub Desktop.
Save jpbland1/ad46617fcc40934b252ce031c7aa5969 to your computer and use it in GitHub Desktop.
wolfSSL ECH cloudflare example
-----BEGIN CERTIFICATE-----
MIIFSTCCBO6gAwIBAgIQCkPt//78N/D9z8Y990Ry+jAKBggqhkjOPQQDAjBKMQsw
CQYDVQQGEwJVUzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEgMB4GA1UEAxMX
Q2xvdWRmbGFyZSBJbmMgRUNDIENBLTMwHhcNMjIwNDAzMDAwMDAwWhcNMjMwNDAz
MjM1OTU5WjB1MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQG
A1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEe
MBwGA1UEAxMVc25pLmNsb3VkZmxhcmVzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZI
zj0DAQcDQgAEDA9hOpdJL/9KiWgepouXcJPn73SrFi5WdS0XrtdiqR74Pj5nvSW4
LrqF7iL2ce9lAi2B64NZAsa1BMfBVeoS26OCA4kwggOFMB8GA1UdIwQYMBaAFKXO
N+rrsHUOlGeItEX62SQQh5YfMB0GA1UdDgQWBBTIStIlPB6Ag7gZlILYMQYlYsPy
jTBQBgNVHREESTBHghVzbmkuY2xvdWRmbGFyZXNzbC5jb22CFWNyeXB0by5jbG91
ZGZsYXJlLmNvbYIXKi5jcnlwdG8uY2xvdWRmbGFyZS5jb20wDgYDVR0PAQH/BAQD
AgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB7BgNVHR8EdDByMDeg
NaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vQ2xvdWRmbGFyZUluY0VDQ0NB
LTMuY3JsMDegNaAzhjFodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vQ2xvdWRmbGFy
ZUluY0VDQ0NBLTMuY3JsMD4GA1UdIAQ3MDUwMwYGZ4EMAQICMCkwJwYIKwYBBQUH
AgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzB2BggrBgEFBQcBAQRqMGgw
JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcw
AoY0aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Nsb3VkZmxhcmVJbmNFQ0ND
QS0zLmNydDAMBgNVHRMBAf8EAjAAMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcA
dgCt9776fP8QyIudPZwePhhqtGcpXc+xDCTKhYY069yCigAAAX/s9bdMAAAEAwBH
MEUCIGhhExr1RjiB36ybuAeLjW6fBCFYw7lsO+/EXahe4irsAiEAhSPzYDi5ZJFj
epAXvT+vi899OHUSCjlyber914EXP0sAdQA1zxkbv7FsV78PrUxtQsu7ticgJlHq
P+Eq76gDwzvWTAAAAX/s9bdMAAAEAwBGMEQCIDAYdG4FiEtqSt7w5xnKi65Pa//B
2hEw0/kGJK3pHPHtAiAWEviowgvh2LCIKNrWwCqJursBpKgTmFVdb2XguRlgBAB2
ALNzdwfhhFD4Y4bWBancEQlKeS2xZwwLh9zwAw55NqWaAAABf+z1t3YAAAQDAEcw
RQIhAJZJqna1edW/7/G6RSN/1GRYOzb375ADR246/awZycPiAiBvnFOC5yy372da
ebvqEioxvDbPgzXrF1f/isFWX6X4LDAKBggqhkjOPQQDAgNJADBGAiEA0f4JyovA
cquL5GOOQpJ2owJGW/bd+dV1qJ4cg65mDVcCIQCuc7hZAu9V640k4UnKhFXiSfiC
mGPgEj+E1q460StmSg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDzTCCArWgAwIBAgIQCjeHZF5ftIwiTv0b7RQMPDANBgkqhkiG9w0BAQsFADBa
MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl
clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTIw
MDEyNzEyNDgwOFoXDTI0MTIzMTIzNTk1OVowSjELMAkGA1UEBhMCVVMxGTAXBgNV
BAoTEENsb3VkZmxhcmUsIEluYy4xIDAeBgNVBAMTF0Nsb3VkZmxhcmUgSW5jIEVD
QyBDQS0zMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEua1NZpkUC0bsH4HRKlAe
nQMVLzQSfS2WuIg4m4Vfj7+7Te9hRsTJc9QkT+DuHM5ss1FxL2ruTAUJd9NyYqSb
16OCAWgwggFkMB0GA1UdDgQWBBSlzjfq67B1DpRniLRF+tkkEIeWHzAfBgNVHSME
GDAWgBTlnVkwgkdYzKz6CFQ2hns6tQRN8DAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0l
BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYI
KwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j
b20wOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL09t
bmlyb290MjAyNS5jcmwwbQYDVR0gBGYwZDA3BglghkgBhv1sAQEwKjAoBggrBgEF
BQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sAQIw
CAYGZ4EMAQIBMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQELBQADggEB
AAUkHd0bsCrrmNaF4zlNXmtXnYJX/OvoMaJXkGUFvhZEOFp3ArnPEELG4ZKk40Un
+ABHLGioVplTVI+tnkDB0A+21w0LOEhsUCxJkAZbZB2LzEgwLt4I4ptJIsCSDBFe
lpKU1fwg3FZs5ZKTv3ocwDfjhUkV+ivhdDkYD7fa86JXWGBPzI6UAPxGezQxPk1H
goE6y/SJXQ7vTQ1unBuCJN0yJV0ReFEQPaA1IwQvZW+cwdFD19Ae8zFnWSfda9J1
CZMRJCQUzym+5iPDuI9yP+kHyCREU3qzuWFloUwOxkgAyXVjBYdwRVKD05WdRerw
6DEdfgkfCv4+3ao8XnTSrLE=
-----END CERTIFICATE-----
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <wolfssl/test.h>
#include <errno.h>
#define SERV_PORT 443
void main()
{
int ret;
byte rd_buf[512];
int sockfd;
WOLFSSL_CTX* ctx;
WOLFSSL* ssl;
WOLFSSL_METHOD* method;
struct sockaddr_in servAddr;
const char message[] =
"GET /cdn-cgi/trace/ HTTP/1.1\r\n"
"Host: crypto.cloudflare.com\r\n"
"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n"
"Accept-Language: en-US,en;q=0.5\r\n"
"Referer: https://www.google.com/\r\n"
"DNT: 1\r\n"
"Connection: keep-alive\r\n"
"Upgrade-Insecure-Requests: 1\r\n"
"Sec-Fetch-Dest: document\r\n"
"Sec-Fetch-Mode: navigate\r\n"
"Sec-Fetch-Site: cross-site\r\n"
"Pragma: no-cache\r\n"
"Cache-Control: no-cache\r\n"
"\r\n";
const char ip_string[] = "162.159.137.85";
uint8_t ech_configs[72];
uint32_t ech_configs_len = 72;
/* this first tls connection is only used to get the retry configs */
/* these configs can also be retrieved from DNS */
/* create and set up socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(SERV_PORT);
// set the ip string to the cloudflare server
servAddr.sin_addr.s_addr = inet_addr( ip_string );
/* connect to socket */
connect(sockfd, (struct sockaddr *) &servAddr, sizeof(servAddr));
/* initialize wolfssl library */
wolfSSL_Init();
method = wolfTLSv1_3_client_method(); /* use TLS v1.3 */
/* make new ssl context */
if ( (ctx = wolfSSL_CTX_new(method)) == NULL) {
err_sys("wolfSSL_CTX_new error");
}
/* set the server name we want to connect to */
ret = wolfSSL_CTX_UseSNI( ctx, WOLFSSL_SNI_HOST_NAME, "crypto.cloudflare.com", strlen("crypto.cloudflare.com") );
if ( ret != WOLFSSL_SUCCESS ) {
printf( "%d", ret );
err_sys("wolfSSL_CTX_UseSNI error");
}
/* make new wolfSSL struct */
if ( (ssl = wolfSSL_new(ctx)) == NULL) {
err_sys("wolfSSL_new error");
}
/* Add cert to ctx */
if (wolfSSL_CTX_load_verify_locations(ctx, "cert.pem", 0) !=
SSL_SUCCESS) {
err_sys("Error loading ca-cert.pem");
}
/* Connect wolfssl to the socket, server, then send message */
wolfSSL_set_fd(ssl, sockfd);
/* this connect will send a grease ech and get the retry configs back */
ret = wolfSSL_connect(ssl);
if (ret != SSL_SUCCESS) {
printf( "%d %d\n", ret, wolfSSL_get_error( ssl, ret ) );
err_sys("Error wolfSSL_connect");
}
/* retrieve the retry configs sent by the server */
ret = wolfSSL_GetEchConfigs(ssl, ech_configs, &ech_configs_len);
if (ret != SSL_SUCCESS) {
printf( "%d %d\n", ret, wolfSSL_get_error( ssl, ret ) );
err_sys("Error wolfSSL_get_ech_configs");
}
/* frees all data before client termination */
wolfSSL_free(ssl);
close(sockfd);
/* now we create a new connection that will send the real ech */
/* create and set up socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(SERV_PORT);
// set the ip string to the cloudflare server
servAddr.sin_addr.s_addr = inet_addr( ip_string );
/* connect to socket */
connect(sockfd, (struct sockaddr *) &servAddr, sizeof(servAddr));
/* make new wolfSSL struct */
if ( (ssl = wolfSSL_new(ctx)) == NULL) {
err_sys("wolfSSL_new error");
}
// set the ech configs taken from dns
ret = wolfSSL_SetEchConfigs(ssl, ech_configs, ech_configs_len);
if ( ret != WOLFSSL_SUCCESS ) {
err_sys("wolfSSL_set_ech_configs error");
}
/* Connect wolfssl to the socket, server, then send message */
wolfSSL_set_fd(ssl, sockfd);
/* this connect will send the real ech */
ret = wolfSSL_connect(ssl);
if (ret != SSL_SUCCESS) {
printf( "%d %d\n", ret, wolfSSL_get_error( ssl, ret ) );
err_sys("Error wolfSSL_connect");
}
wolfSSL_write(ssl, message, strlen(message));
do
{
ret = wolfSSL_read( ssl, rd_buf, sizeof(rd_buf) );
printf( "%.*s", ret, rd_buf );
/* read until the chunk size is 0 */
} while ( rd_buf[0] != '0' );
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
wolfSSL_Cleanup();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment