Handle HTTP CONNECT

#246
This commit is contained in:
ruti 2025-01-04 15:32:36 +03:00
parent 4336b2b9d0
commit d919bd2f29
4 changed files with 47 additions and 1 deletions

View File

@ -45,6 +45,7 @@ enum eid {
#define FLAG_S4 1 #define FLAG_S4 1
#define FLAG_S5 2 #define FLAG_S5 2
#define FLAG_CONN 4 #define FLAG_CONN 4
#define FLAG_HTTP 8
#ifdef EID_STR #ifdef EID_STR
char *eid_name[] = { char *eid_name[] = {

4
main.c
View File

@ -132,6 +132,7 @@ const struct option options[] = {
{"no-domain", 0, 0, 'N'}, {"no-domain", 0, 0, 'N'},
{"no-ipv6", 0, 0, 'X'}, {"no-ipv6", 0, 0, 'X'},
{"no-udp", 0, 0, 'U'}, {"no-udp", 0, 0, 'U'},
{"allow-http", 0, 0, 'G'},
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
{"version", 0, 0, 'v'}, {"version", 0, 0, 'v'},
{"ip", 1, 0, 'i'}, {"ip", 1, 0, 'i'},
@ -674,6 +675,9 @@ int main(int argc, char **argv)
case 'U': case 'U':
params.udp = 0; params.udp = 0;
break; break;
case 'G':
params.http_connect = 1;
break;
#ifdef __linux__ #ifdef __linux__
case 'E': case 'E':
params.transparent = 1; params.transparent = 1;

View File

@ -111,12 +111,13 @@ struct params {
bool ipv6; bool ipv6;
bool resolve; bool resolve;
bool udp; bool udp;
bool transparent;
bool http_connect;
int max_open; int max_open;
int debug; int debug;
size_t bfsize; size_t bfsize;
struct sockaddr_in6 baddr; struct sockaddr_in6 baddr;
struct sockaddr_in6 laddr; struct sockaddr_in6 laddr;
bool transparent;
struct mphdr *mempool; struct mphdr *mempool;
const char *protect_path; const char *protect_path;

40
proxy.c
View File

@ -13,6 +13,7 @@
#include "conev.h" #include "conev.h"
#include "extend.h" #include "extend.h"
#include "error.h" #include "error.h"
#include "packets.h"
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
@ -128,6 +129,8 @@ static int resolve(char *host, int len,
hints.ai_socktype = type; hints.ai_socktype = type;
hints.ai_flags = AI_ADDRCONFIG; hints.ai_flags = AI_ADDRCONFIG;
if (!params.resolve)
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = params.ipv6 ? AF_UNSPEC : AF_INET; hints.ai_family = params.ipv6 ? AF_UNSPEC : AF_INET;
char rchar = host[len]; char rchar = host[len];
@ -205,6 +208,14 @@ static int resp_error(int fd, int e, int flag)
} }
return resp_s5_error(fd, e); 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__ #ifdef __linux__
if (params.transparent && if (params.transparent &&
(e == ECONNREFUSED || e == ETIMEDOUT)) { (e == ECONNREFUSED || e == ETIMEDOUT)) {
@ -334,6 +345,26 @@ static int s5_set_addr(char *buffer, size_t n,
} }
static int http_get_addr(const char *buff,
size_t n, struct sockaddr_ina *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(struct sockaddr_ina *dst, int type) static int remote_sock(struct sockaddr_ina *dst, int type)
{ {
if (params.baddr.sin6_family == AF_INET6) { if (params.baddr.sin6_family == AF_INET6) {
@ -841,6 +872,15 @@ static inline int on_request(struct poolhd *pool, struct eval *val,
} }
error = connect_hook(pool, val, &dst, EV_CONNECT); 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 { else {
LOG(LOG_E, "ss: invalid version: 0x%x (%zd)\n", *buffer, n); LOG(LOG_E, "ss: invalid version: 0x%x (%zd)\n", *buffer, n);
return -1; return -1;