Feature #4247 ยป [TVHE-devel] enable PROXY protocol and X-Forwarded-For.diff
tvheadend/src/config.c 2017-02-18 13:07:29.000000000 +0100 | ||
---|---|---|
1676 | 1676 |
config.idnode.in_class = &config_class; |
1677 | 1677 |
config.ui_quicktips = 1; |
1678 | 1678 |
config.digest = 1; |
1679 |
config.proxy = 0; |
|
1679 | 1680 |
config.realm = strdup("tvheadend"); |
1680 | 1681 |
config.info_area = strdup("login,storage,time"); |
1681 | 1682 |
config.cookie_expires = 7; |
... | ... | |
2127 | 2128 |
.opts = PO_EXPERT, |
2128 | 2129 |
.group = 1 |
2129 | 2130 |
}, |
2131 |
{ |
|
2132 |
.type = PT_BOOL, |
|
2133 |
.id = "proxy", |
|
2134 |
.name = N_("Use PROXY protocol & X-Forwarded-For"), |
|
2135 |
.desc = N_("PROXY protocol is an extension for support incoming " |
|
2136 |
"TCP connections from a remote server (like a firewall) " |
|
2137 |
"sending the original IP address of the client. " |
|
2138 |
"The HTTP header 'X-Forwarded-For' do the same with " |
|
2139 |
"HTTP connections. Both enable tunneled connections." |
|
2140 |
"This option should be disabled for standard usage."), |
|
2141 |
.off = offsetof(config_t, proxy), |
|
2142 |
.opts = PO_EXPERT, |
|
2143 |
.group = 1 |
|
2144 |
}, |
|
2130 | 2145 |
{ |
2131 | 2146 |
.type = PT_U32, |
2132 | 2147 |
.intextra = INTEXTRA_RANGE(1, 0x7ff, 1), |
tvheadend/src/config.h 2017-02-18 13:07:29.000000000 +0100 | ||
---|---|---|
34 | 34 |
int uilevel_nochange; |
35 | 35 |
int ui_quicktips; |
36 | 36 |
int digest; |
37 |
int proxy; |
|
37 | 38 |
char *realm; |
38 | 39 |
char *wizard; |
39 | 40 |
char *full_version; |
tvheadend/src/http.c 2017-02-18 13:07:29.000000000 +0100 | ||
---|---|---|
1100 | 1100 |
char authbuf[150]; |
1101 | 1101 | |
1102 | 1102 |
hc->hc_url_orig = tvh_strdupa(hc->hc_url); |
1103 | ||
1104 |
v = (config.proxy) ? http_arg_get(&hc->hc_args, "x-forwarded-for") : NULL; |
|
1105 |
if (v) |
|
1106 |
tcp_get_sockaddr((struct sockaddr*)hc->hc_peer, v); |
|
1107 | ||
1103 | 1108 |
tcp_get_str_from_ip((struct sockaddr*)hc->hc_peer, authbuf, sizeof(authbuf)); |
1109 | ||
1104 | 1110 |
hc->hc_peer_ipstr = tvh_strdupa(authbuf); |
1105 | 1111 |
hc->hc_representative = hc->hc_peer_ipstr; |
1106 | 1112 |
hc->hc_username = NULL; |
... | ... | |
1460 | 1466 |
if ((cmdline = tcp_read_line(hc->hc_fd, &spill)) == NULL) |
1461 | 1467 |
goto error; |
1462 | 1468 | |
1469 |
// PROXY Protocol v1 support |
|
1470 |
// Format: 'PROXY TCP4 192.168.0.1 192.168.0.11 56324 9981\r\n' |
|
1471 |
// SRC-ADDRESS DST-ADDRESS SPORT DPORT |
|
1472 |
// |
|
1473 |
if ((config.proxy) && (strlen(cmdline) >= 6) && (strncmp(cmdline,"PROXY ",6) == 0 )) { |
|
1474 |
tvhinfo(LS_HTTP, "[PROXY] PROXY protocol detected! cmdline='%s'",cmdline); |
|
1475 | ||
1476 |
char* pl = cmdline + 6; |
|
1477 | ||
1478 |
if ((cmdline = tcp_read_line(hc->hc_fd, &spill)) == NULL) { |
|
1479 |
goto error; // No more data after the PROXY protocol |
|
1480 |
} |
|
1481 | ||
1482 |
if ( (strlen(pl) >= 7) && (strncmp(pl,"UNKNOWN",7) == 0)) |
|
1483 |
goto error; // Unknown PROXY protocol |
|
1484 |
|
|
1485 |
if ( (strlen(pl) < 5) || (strncmp(pl,"TCP4 ",5) != 0)) |
|
1486 |
goto error; // Only IPv4 supported |
|
1487 |
pl += 5; |
|
1488 | ||
1489 |
// Check the SRC-ADDRESS |
|
1490 |
c = pl; |
|
1491 |
char ch; |
|
1492 |
for ( ;; ) { |
|
1493 |
if (strlen(pl) == 0) goto error; // Incomplete PROXY format |
|
1494 |
ch = *pl++; |
|
1495 |
if (ch == ' ') break; |
|
1496 |
if (ch != '.' && (ch < '0' || ch > '9')) goto error; // Not valid IP address |
|
1497 |
} |
|
1498 |
if (((pl-c) < 8) || ((pl-c) > 16)) goto error; // Not valid IP address |
|
1499 |
|
|
1500 |
// Here 'c' points to a dotted IPv4 SRC-ADRRESS |
|
1501 |
char srcaddr[16]; |
|
1502 |
memset(srcaddr, 0, 16); |
|
1503 |
strncpy(srcaddr, c, (pl-c)-1); |
|
1504 | ||
1505 |
// Don't care about DST-ADDRESS, SRC-PORT & DST-PORT |
|
1506 |
// All it's OK, push the original client IP |
|
1507 |
tvhinfo(LS_HTTP, "[PROXY] Original source='%s'",srcaddr); |
|
1508 |
http_arg_set(&hc->hc_args, "x-forwarded-for", srcaddr); |
|
1509 |
} |
|
1510 |
|
|
1463 | 1511 |
if((n = http_tokenize(cmdline, argv, 3, -1)) != 3) |
1464 | 1512 |
goto error; |
1465 | 1513 |
|
tvheadend/src/tcp.c 2017-02-18 13:07:29.0000000007 +0100 | ||
---|---|---|
446 | 446 |
/** |
447 | 447 |
* |
448 | 448 |
*/ |
449 |
int |
|
450 |
tcp_get_sockaddr(struct sockaddr *sa, const char *s) |
|
451 |
{ |
|
452 |
if(sa == NULL || s == NULL) |
|
453 |
return -1; |
|
454 | ||
455 |
struct sockaddr_in *sin = (struct sockaddr_in*)sa; |
|
456 |
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; |
|
457 | ||
458 |
if (inet_pton(AF_INET, s, &sin->sin_addr) == 1) |
|
459 |
sa->sa_family = AF_INET; |
|
460 |
else if (inet_pton(AF_INET6, s, &sin6->sin6_addr) == 1) |
|
461 |
sa->sa_family = AF_INET6; |
|
462 |
else |
|
463 |
return -1; |
|
464 | ||
465 |
return 0; |
|
466 |
} |
|
467 | ||
468 |
/** |
|
469 |
* |
|
470 |
*/ |
|
449 | 471 |
static tvhpoll_t *tcp_server_poll; |
450 | 472 |
static uint32_t tcp_server_launch_id; |
451 | 473 |
tvheadend/src/tcp.h 2017-02-18 13:07:29.000000000 +0100 | ||
---|---|---|
94 | 94 | |
95 | 95 |
char *tcp_get_str_from_ip(const struct sockaddr *sa, char *dst, size_t maxlen); |
96 | 96 | |
97 |
int tcp_get_sockaddr(struct sockaddr *sa, const char *s); |
|
98 | ||
97 | 99 |
struct sockaddr *tcp_get_ip_from_str(const char *str, struct sockaddr *sa); |
98 | 100 | |
99 | 101 |
int tcp_socket_dead(int fd); |