1
0
mirror of https://github.com/coturn/coturn.git synced 2025-10-31 23:11:28 +01:00

Add support for proxy protocol V1

This commit is contained in:
Peter Linss 2020-11-18 16:43:24 -08:00
parent ae2ee1f4e4
commit c00d69e67f
No known key found for this signature in database
GPG Key ID: 0ED32B6657FA9FE0

View File

@ -2166,6 +2166,101 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd)
}
#endif
static size_t proxy_string_field(char *field, size_t max, uint8_t *buf, size_t index, size_t len)
{
size_t count = 0;
while((index < len) && (count < max)) {
if((0x20 == buf[index]) || (0x0D == buf[index])) {
field[count] = 0x00;
return ++index;
}
field[count++] = buf[index++];
}
return 0;
}
static ssize_t socket_parse_proxy_v1(ioa_socket_handle s, uint8_t *buf, size_t len)
{
if(len < 11) {
return 0 ;
}
/* Check for proxy-v1 magic field */
char magic[] = {0x50, 0x52, 0x4F, 0x58, 0x59, 0x20};
if(memcmp(magic, buf, sizeof(magic))) {
return -1;
}
/* Read family */
char tcp4[] = {0x54, 0x43, 0x50, 0x34, 0x20};
char tcp6[] = {0x54, 0x43, 0x50, 0x36, 0x20};
int family;
if(0 == memcmp(tcp4, &buf[6], sizeof(tcp4))) { /* IPv4 */
family = AF_INET;
} else if(0 == memcmp(tcp6, &buf[6], sizeof(tcp6))) { /* IPv6 */
family = AF_INET6;
} else {
return -1;
}
char saddr[40];
char daddr[40];
char sport[6];
char dport[6];
size_t tlen = 11;
/* Read source address */
tlen = proxy_string_field(saddr, sizeof(saddr), buf, tlen, len);
if(0 == tlen) return -1;
/* Read dest address */
tlen = proxy_string_field(daddr, sizeof(daddr), buf, tlen, len);
if(0 == tlen) return -1;
/* Read source port */
tlen = proxy_string_field(sport, sizeof(sport), buf, tlen, len);
if(0 == tlen) return -1;
/* Read dest port */
tlen = proxy_string_field(dport, sizeof(dport), buf, tlen, len);
if(0 == tlen) return -1;
/* Final line feed */
if ((len <= tlen) || (0x0A != buf[tlen])) return -1;
tlen++;
int sport_int = atoi(sport);
int dport_int = atoi(dport);
if((sport_int < 0) || (0xFFFF < sport_int)) return -1;
if((dport_int < 0) || (0xFFFF < dport_int)) return -1;
if (AF_INET == family) {
struct sockaddr_in remote, local;
remote.sin_family = local.sin_family = AF_INET;
if(1 != inet_pton(AF_INET, saddr, &remote.sin_addr.s_addr)) return -1;
if(1 != inet_pton(AF_INET, daddr, &local.sin_addr.s_addr)) return -1;
remote.sin_port = htons((uint16_t)sport_int);
local.sin_port = htons((uint16_t)dport_int);
addr_cpy4(&(s->local_addr), &local);
addr_cpy4(&(s->remote_addr), &remote);
} else {
struct sockaddr_in6 remote, local;
remote.sin6_family = local.sin6_family = AF_INET6;
if(1 != inet_pton(AF_INET6, saddr, &remote.sin6_addr.s6_addr)) return -1;
if(1 != inet_pton(AF_INET6, daddr, &local.sin6_addr.s6_addr)) return -1;
remote.sin6_port = htons((uint16_t)sport_int);
local.sin6_port = htons((uint16_t)dport_int);
addr_cpy6(&(s->local_addr), &local);
addr_cpy6(&(s->remote_addr), &remote);
}
return tlen;
}
static ssize_t socket_parse_proxy_v2(ioa_socket_handle s, uint8_t *buf, size_t len)
{
if(len < 16){
@ -2227,6 +2322,16 @@ static ssize_t socket_parse_proxy_v2(ioa_socket_handle s, uint8_t *buf, size_t l
return tlen;
}
static ssize_t socket_parse_proxy(ioa_socket_handle s, uint8_t *buf, size_t len)
{
ssize_t tlen = socket_parse_proxy_v2(s, buf, len);
if(-1 == tlen) {
tlen = socket_parse_proxy_v1(s, buf, len);
}
return tlen;
}
static int socket_input_worker(ioa_socket_handle s)
{
int len = 0;
@ -2450,7 +2555,7 @@ static int socket_input_worker(ioa_socket_handle s)
blen=(ev_ssize_t)STUN_BUFFER_SIZE;
if(s->st == TCP_SOCKET_PROXY){
ssize_t tlen = socket_parse_proxy_v2(s, buf_elem->buf.buf, blen);
ssize_t tlen = socket_parse_proxy(s, buf_elem->buf.buf, blen);
blen = 0;
if (tlen < 0){
s->tobeclosed = 1;