Added Reverse Proxy Header Support
This commit is contained in:
16
src/client.c
16
src/client.c
@ -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);
|
||||
|
113
src/rev_proxy.c
113
src/rev_proxy.c
@ -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:
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user