From ec6c82006ad712190724c7ca545497a1f6813574 Mon Sep 17 00:00:00 2001 From: ruti <> Date: Tue, 14 Jan 2025 18:39:39 +0300 Subject: [PATCH] Handle HTTP CONNECT --- conev.h | 1 + main.c | 4 ++++ params.h | 3 ++- proxy.c | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/conev.h b/conev.h index 57d515b..bb5cc13 100644 --- a/conev.h +++ b/conev.h @@ -51,6 +51,7 @@ enum eid { #define FLAG_S4 1 #define FLAG_S5 2 #define FLAG_CONN 4 +#define FLAG_HTTP 8 #ifdef EID_STR char *eid_name[] = { diff --git a/main.c b/main.c index 46dd460..e1565f0 100644 --- a/main.c +++ b/main.c @@ -132,6 +132,7 @@ const struct option options[] = { {"no-domain", 0, 0, 'N'}, {"no-ipv6", 0, 0, 'X'}, {"no-udp", 0, 0, 'U'}, + {"http-connect", 0, 0, 'G'}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'v'}, {"ip", 1, 0, 'i'}, @@ -675,6 +676,9 @@ int main(int argc, char **argv) case 'U': params.udp = 0; break; + case 'G': + params.http_connect = 1; + break; #ifdef __linux__ case 'E': params.transparent = 1; diff --git a/params.h b/params.h index 526b915..55c2187 100644 --- a/params.h +++ b/params.h @@ -112,12 +112,13 @@ struct params { bool ipv6; bool resolve; bool udp; + bool transparent; + bool http_connect; int max_open; int debug; size_t bfsize; union sockaddr_u baddr; union sockaddr_u laddr; - bool transparent; struct mphdr *mempool; const char *protect_path; diff --git a/proxy.c b/proxy.c index e3239a6..cf74765 100644 --- a/proxy.c +++ b/proxy.c @@ -13,6 +13,7 @@ #include "conev.h" #include "extend.h" #include "error.h" +#include "packets.h" #ifdef _WIN32 #include @@ -125,6 +126,8 @@ static int resolve(char *host, int len, hints.ai_socktype = type; hints.ai_flags = AI_ADDRCONFIG; + if (!params.resolve) + hints.ai_flags |= AI_NUMERICHOST; hints.ai_family = params.ipv6 ? AF_UNSPEC : AF_INET; char rchar = host[len]; @@ -202,6 +205,14 @@ static int resp_error(int fd, int e, int flag) } return resp_s5_error(fd, e); } + else if (flag == FLAG_HTTP) { + if (!e) { + static const char r[] = "HTTP/1.1 200 OK\r\n\r\n"; + return send(fd, r, sizeof(r) - 1, 0); + } + static const char r[] = "HTTP/1.1 503 Fail\r\n\r\n"; + return send(fd, r, sizeof(r) - 1, 0); + } #ifdef __linux__ if (params.transparent && (e == ECONNREFUSED || e == ETIMEDOUT)) { @@ -331,6 +342,25 @@ static int s5_set_addr(char *buffer, size_t n, } +static int http_get_addr( + const char *buff, size_t n, union sockaddr_u *dst) +{ + char *host = 0; + uint16_t port = 0; + int host_len = parse_http(buff, n, &host, &port); + + if (host_len < 3 || host_len > 255) { + return -1; + } + if (resolve(host, host_len, dst, SOCK_STREAM)) { + LOG(LOG_E, "not resolved: %.*s\n", host_len, host); + return -1; + } + dst->in.sin_port = htons(port); + return 0; +} + + static int remote_sock(union sockaddr_u *dst, int type) { if (params.baddr.sa.sa_family == AF_INET6) { @@ -838,6 +868,15 @@ static inline int on_request(struct poolhd *pool, struct eval *val, } error = connect_hook(pool, val, &dst, EV_CONNECT); } + else if (params.http_connect + && n > 7 && !memcmp(buffer, "CONNECT", 7)) { + val->flag = FLAG_HTTP; + + if (http_get_addr(buffer, n, &dst)) { + return -1; + } + error = connect_hook(pool, val, &dst, EV_CONNECT); + } else { LOG(LOG_E, "ss: invalid version: 0x%x (%zd)\n", *buffer, n); return -1;