Added Reverse Proxy Header Support

This commit is contained in:
2021-03-18 19:56:50 +01:00
parent 63781472fa
commit 10464f3f30
3 changed files with 127 additions and 11 deletions

View File

@ -354,10 +354,18 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
http_add_header_field(&res.hdr, "Transfer-Encoding", "chunked");
}
}
} else if (conf->type != CONFIG_TYPE_LOCAL) {
} else if (conf->type == CONFIG_TYPE_REVERSE_PROXY) {
print("Reverse proxy for " BLD_STR "%s:%i" CLR_STR, conf->rev_proxy.hostname, conf->rev_proxy.port);
http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL);
ret = rev_proxy_init(&req, &res, conf, client, &custom_status, err_msg);
use_rev_proxy = ret == 0;
if (http_get_header_field(&res.hdr, "Date") == NULL)
http_add_header_field(&res.hdr, "Date", http_get_date(buf0, sizeof(buf0)));
if (http_get_header_field(&res.hdr, "Server") == NULL)
http_add_header_field(&res.hdr, "Server", SERVER_STR);
} else {
print(ERR_STR "Unknown host type: %i" CLR_STR, conf->type);
res.status = http_get_status(501);
@ -407,12 +415,8 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
} else if (http_get_header_field(&res.hdr, "Transfer-Encoding") == NULL) {
server_keep_alive = 0;
}
} else {
http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL);
http_add_header_field(&res.hdr, "Date", http_get_date(buf0, sizeof(buf0)));
http_add_header_field(&res.hdr, "Server", SERVER_STR);
}
char *conn = http_get_header_field(&res.hdr, "Connection");
int close_proxy = conn == NULL || (strcmp(conn, "keep-alive") != 0 && strcmp(conn, "Keep-Alive") != 0);
http_remove_header_field(&res.hdr, "Connection", HTTP_REMOVE_ALL);

View File

@ -11,9 +11,113 @@ sock rev_proxy;
char *rev_proxy_host = NULL;
struct timeval server_timeout = {.tv_sec = SERVER_TIMEOUT, .tv_usec = 0};
int rev_proxy_request_header(http_req *req, int enc) {
char buf1[256];
char buf2[256];
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "Connection", "keep-alive");
char *via = http_get_header_field(&req->hdr, "Via");
sprintf(buf1, "HTTP/%s %s", req->version, DEFAULT_HOST);
if (via == NULL) {
http_add_header_field(&req->hdr, "Via", buf1);
} else {
sprintf(buf2, "%s, %s", via, buf1);
http_remove_header_field(&req->hdr, "Via", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "Via", buf2);
}
char *host = http_get_header_field(&req->hdr, "Host");
char *forwarded = http_get_header_field(&req->hdr, "Forwarded");
int client_ipv6 = strchr(client_addr_str, ':') != NULL;
int server_ipv6 = strchr(server_addr_str, ':') != NULL;
sprintf(buf1, "by=%s%s%s;for=%s%s%s;host=%s;proto=%s",
server_ipv6 ? "\"[" : "", server_addr_str, server_ipv6 ? "]\"" : "",
client_ipv6 ? "\"[" : "", client_addr_str, client_ipv6 ? "]\"" : "",
host, enc ? "https" : "http");
if (forwarded == NULL) {
// TODO escape IPv6 addresses
http_add_header_field(&req->hdr, "Forwarded", buf1);
} else {
sprintf(buf2, "%s, %s", forwarded, buf1);
http_remove_header_field(&req->hdr, "Forwarded", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "Forwarded", buf2);
}
char *xff = http_get_header_field(&req->hdr, "X-Forwarded-For");
if (xff == NULL) {
http_add_header_field(&req->hdr, "X-Forwarded-For", client_addr_str);
} else {
sprintf(buf1, "%s, %s", xff, client_addr_str);
http_remove_header_field(&req->hdr, "X-Forwarded-For", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "X-Forwarded-For", buf1);
}
char *xfh = http_get_header_field(&req->hdr, "X-Forwarded-Host");
if (xfh == NULL) {
if (forwarded == NULL) {
http_add_header_field(&req->hdr, "X-Forwarded-Host", host);
} else {
char *ptr = strchr(forwarded, ',');
unsigned long len;
if (ptr != NULL) len = ptr - forwarded;
else len = strlen(forwarded);
ptr = strstr(forwarded, "host=");
if ((ptr - forwarded) < len) {
char *end = strchr(ptr, ';');
if (end == NULL) len -= (ptr - forwarded);
else len = (end - ptr);
len -= 5;
sprintf(buf1, "%.*s", (int) len, ptr + 5);
http_add_header_field(&req->hdr, "X-Forwarded-Host", buf1);
}
}
}
char *xfp = http_get_header_field(&req->hdr, "X-Forwarded-Proto");
if (xfp == NULL) {
if (forwarded == NULL) {
http_add_header_field(&req->hdr, "X-Forwarded-Proto", enc ? "https" : "http");
} else {
char *ptr = strchr(forwarded, ',');
unsigned long len;
if (ptr != NULL) len = ptr - forwarded;
else len = strlen(forwarded);
ptr = strstr(forwarded, "proto=");
if ((ptr - forwarded) < len) {
char *end = strchr(ptr, ';');
if (end == NULL) len -= (ptr - forwarded);
else len = (end - ptr);
len -= 6;
sprintf(buf1, "%.*s", (int) len, ptr + 6);
http_add_header_field(&req->hdr, "X-Forwarded-Proto", buf1);
}
}
}
return 0;
}
int rev_proxy_response_header(http_req *req, http_res *res) {
char buf1[256];
char buf2[256];
char *via = http_get_header_field(&res->hdr, "Via");
sprintf(buf1, "HTTP/%s %s", req->version, DEFAULT_HOST);
if (via == NULL) {
http_add_header_field(&res->hdr, "Via", buf1);
} else {
sprintf(buf2, "%s, %s", via, buf1);
http_remove_header_field(&res->hdr, "Via", HTTP_REMOVE_ALL);
http_add_header_field(&res->hdr, "Via", buf2);
}
return 0;
}
int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client, http_status *custom_status,
char * err_msg) {
char *err_msg) {
char buffer[CHUNK_SIZE];
long ret;
int tries = 0;
@ -97,10 +201,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
print(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i" CLR_STR, buffer, conf->rev_proxy.port);
rev_proxy:
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "Connection", "keep-alive");
http_remove_header_field(&req->hdr, "X-Forwarded-For", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "X-Forwarded-For", client_addr_str);
rev_proxy_request_header(req, (int) client->enc);
ret = http_send_request(&rev_proxy, req);
if (ret < 0) {
@ -222,6 +323,8 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
}
sock_recv(&rev_proxy, buffer, header_len, 0);
rev_proxy_response_header(req, res);
return 0;
proxy_err:

View File

@ -8,4 +8,13 @@
#ifndef NECRONDA_SERVER_REV_PROXY_H
#define NECRONDA_SERVER_REV_PROXY_H
int rev_proxy_request_header(http_req *req, int enc);
int rev_proxy_response_header(http_req *req, http_res *res);
int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client, http_status *custom_status,
char *err_msg);
int rev_proxy_send(sock *client, int chunked, unsigned long len_to_send);
#endif //NECRONDA_SERVER_REV_PROXY_H