mirror of
https://github.com/coturn/coturn.git
synced 2025-11-04 17:01:39 +01:00
Merge pull request #479 from WaxieSDR/master
Add support for reverse proxy connections
This commit is contained in:
commit
db68c76195
@ -322,6 +322,10 @@ Options with values:
|
|||||||
--alt-tls-listening-port Alternative listening port for TLS and DTLS protocols.
|
--alt-tls-listening-port Alternative listening port for TLS and DTLS protocols.
|
||||||
Default (or zero) value means "TLS listening port plus one".
|
Default (or zero) value means "TLS listening port plus one".
|
||||||
|
|
||||||
|
--tcp-proxy-port Support connections from TCP loadbalancer on this port. The loadbalancer
|
||||||
|
should use the binary proxy protocol.
|
||||||
|
(https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)
|
||||||
|
|
||||||
--aux-server Auxiliary STUN/TURN server listening endpoint.
|
--aux-server Auxiliary STUN/TURN server listening endpoint.
|
||||||
Aux servers have almost full TURN and STUN functionality.
|
Aux servers have almost full TURN and STUN functionality.
|
||||||
The (minor) limitations are:
|
The (minor) limitations are:
|
||||||
|
|||||||
@ -45,6 +45,14 @@
|
|||||||
#
|
#
|
||||||
#alt-tls-listening-port=0
|
#alt-tls-listening-port=0
|
||||||
|
|
||||||
|
# Some network setups will require using a TCP reverse proxy in front
|
||||||
|
# of the STUN server. If the proxy port option is set a single listener
|
||||||
|
# is started on the given port that accepts connections using the
|
||||||
|
# haproxy proxy protocol v2.
|
||||||
|
# (https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)
|
||||||
|
#
|
||||||
|
#tcp-proxy-port=5555
|
||||||
|
|
||||||
# Listener IP address of relay server. Multiple listeners can be specified.
|
# Listener IP address of relay server. Multiple listeners can be specified.
|
||||||
# If no IP(s) specified in the config file or in the command line options,
|
# If no IP(s) specified in the config file or in the command line options,
|
||||||
# then all IPv4 and IPv6 system IPs will be used for listening.
|
# then all IPv4 and IPv6 system IPs will be used for listening.
|
||||||
|
|||||||
@ -481,6 +481,12 @@ Alternative listening port for TLS and DTLS protocols.
|
|||||||
Default (or zero) value means "TLS listening port plus one".
|
Default (or zero) value means "TLS listening port plus one".
|
||||||
.TP
|
.TP
|
||||||
.B
|
.B
|
||||||
|
\fB\-\-tcp\-proxy\-port\fP
|
||||||
|
Support connections from TCP loadbalancer on this port. The loadbalancer
|
||||||
|
should use the binary proxy protocol.
|
||||||
|
(https://www.haproxy.org/download/1.8/doc/proxy\-protocol.txt)
|
||||||
|
.TP
|
||||||
|
.B
|
||||||
\fB\-\-aux\-server\fP
|
\fB\-\-aux\-server\fP
|
||||||
Auxiliary STUN/TURN server listening endpoint.
|
Auxiliary STUN/TURN server listening endpoint.
|
||||||
Aux servers have almost full TURN and STUN functionality.
|
Aux servers have almost full TURN and STUN functionality.
|
||||||
|
|||||||
@ -439,6 +439,7 @@ int set_raw_socket_tos(evutil_socket_t fd, int family, int tos)
|
|||||||
int is_stream_socket(int st) {
|
int is_stream_socket(int st) {
|
||||||
switch(st) {
|
switch(st) {
|
||||||
case TCP_SOCKET:
|
case TCP_SOCKET:
|
||||||
|
case TCP_SOCKET_PROXY:
|
||||||
case TLS_SOCKET:
|
case TLS_SOCKET:
|
||||||
case TENTATIVE_TCP_SOCKET:
|
case TENTATIVE_TCP_SOCKET:
|
||||||
case SCTP_SOCKET:
|
case SCTP_SOCKET:
|
||||||
|
|||||||
@ -110,8 +110,8 @@ NULL, PTHREAD_MUTEX_INITIALIZER,
|
|||||||
//////////////// Common params ////////////////////
|
//////////////// Common params ////////////////////
|
||||||
TURN_VERBOSE_NONE,0,0,0,0,
|
TURN_VERBOSE_NONE,0,0,0,0,
|
||||||
"/var/run/turnserver.pid",
|
"/var/run/turnserver.pid",
|
||||||
DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1,
|
DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,0,1,
|
||||||
0,0,0,0,
|
0,0,0,0,0,
|
||||||
"",
|
"",
|
||||||
"",0,
|
"",0,
|
||||||
{
|
{
|
||||||
@ -402,6 +402,8 @@ static char Usage[] = "Usage: turnserver [options]\n"
|
|||||||
" or in old RFC 3489 sense, default is \"listening port plus one\").\n"
|
" or in old RFC 3489 sense, default is \"listening port plus one\").\n"
|
||||||
" --alt-tls-listening-port <port> Alternative listening port for TLS and DTLS,\n"
|
" --alt-tls-listening-port <port> Alternative listening port for TLS and DTLS,\n"
|
||||||
" the default is \"TLS/DTLS port plus one\".\n"
|
" the default is \"TLS/DTLS port plus one\".\n"
|
||||||
|
" --tcp-proxy-port <port> Support connections from TCP loadbalancer on this port. The loadbalancer should\n"
|
||||||
|
" use the binary proxy protocol (https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)\n"
|
||||||
" -L, --listening-ip <ip> Listener IP address of relay server. Multiple listeners can be specified.\n"
|
" -L, --listening-ip <ip> Listener IP address of relay server. Multiple listeners can be specified.\n"
|
||||||
" --aux-server <ip:port> Auxiliary STUN/TURN server listening endpoint.\n"
|
" --aux-server <ip:port> Auxiliary STUN/TURN server listening endpoint.\n"
|
||||||
" Auxiliary servers do not have alternative ports and\n"
|
" Auxiliary servers do not have alternative ports and\n"
|
||||||
@ -713,6 +715,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
|
|||||||
enum EXTRA_OPTS {
|
enum EXTRA_OPTS {
|
||||||
NO_UDP_OPT=256,
|
NO_UDP_OPT=256,
|
||||||
NO_TCP_OPT,
|
NO_TCP_OPT,
|
||||||
|
TCP_PROXY_PORT_OPT,
|
||||||
NO_TLS_OPT,
|
NO_TLS_OPT,
|
||||||
NO_DTLS_OPT,
|
NO_DTLS_OPT,
|
||||||
NO_UDP_RELAY_OPT,
|
NO_UDP_RELAY_OPT,
|
||||||
@ -805,6 +808,7 @@ static const struct myoption long_options[] = {
|
|||||||
{ "tls-listening-port", required_argument, NULL, TLS_PORT_OPT },
|
{ "tls-listening-port", required_argument, NULL, TLS_PORT_OPT },
|
||||||
{ "alt-listening-port", required_argument, NULL, ALT_PORT_OPT },
|
{ "alt-listening-port", required_argument, NULL, ALT_PORT_OPT },
|
||||||
{ "alt-tls-listening-port", required_argument, NULL, ALT_TLS_PORT_OPT },
|
{ "alt-tls-listening-port", required_argument, NULL, ALT_TLS_PORT_OPT },
|
||||||
|
{ "tcp-proxy-port", required_argument, NULL, TCP_PROXY_PORT_OPT },
|
||||||
{ "listening-ip", required_argument, NULL, 'L' },
|
{ "listening-ip", required_argument, NULL, 'L' },
|
||||||
{ "relay-device", required_argument, NULL, 'i' },
|
{ "relay-device", required_argument, NULL, 'i' },
|
||||||
{ "relay-ip", required_argument, NULL, 'E' },
|
{ "relay-ip", required_argument, NULL, 'E' },
|
||||||
@ -1267,6 +1271,10 @@ static void set_option(int c, char *value)
|
|||||||
case ALT_TLS_PORT_OPT:
|
case ALT_TLS_PORT_OPT:
|
||||||
turn_params.alt_tls_listener_port = atoi(value);
|
turn_params.alt_tls_listener_port = atoi(value);
|
||||||
break;
|
break;
|
||||||
|
case TCP_PROXY_PORT_OPT:
|
||||||
|
turn_params.tcp_proxy_port = atoi(value);
|
||||||
|
turn_params.tcp_use_proxy = 1;
|
||||||
|
break;
|
||||||
case MIN_PORT_OPT:
|
case MIN_PORT_OPT:
|
||||||
turn_params.min_port = atoi(value);
|
turn_params.min_port = atoi(value);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -226,10 +226,12 @@ typedef struct _turn_params_ {
|
|||||||
int tls_listener_port;
|
int tls_listener_port;
|
||||||
int alt_listener_port;
|
int alt_listener_port;
|
||||||
int alt_tls_listener_port;
|
int alt_tls_listener_port;
|
||||||
|
int tcp_proxy_port;
|
||||||
int rfc5780;
|
int rfc5780;
|
||||||
|
|
||||||
int no_udp;
|
int no_udp;
|
||||||
int no_tcp;
|
int no_tcp;
|
||||||
|
int tcp_use_proxy;
|
||||||
|
|
||||||
vint no_tcp_relay;
|
vint no_tcp_relay;
|
||||||
vint no_udp_relay;
|
vint no_udp_relay;
|
||||||
|
|||||||
@ -1473,7 +1473,7 @@ static void setup_tcp_listener_servers(ioa_engine_handle e, struct relay_server
|
|||||||
/* Create listeners */
|
/* Create listeners */
|
||||||
|
|
||||||
/* Aux TCP servers */
|
/* Aux TCP servers */
|
||||||
if(!turn_params.no_tls || !turn_params.no_tcp) {
|
if(!turn_params.tcp_use_proxy && (!turn_params.no_tls || !turn_params.no_tcp)) {
|
||||||
|
|
||||||
for(i=0; i<turn_params.aux_servers_list.size; i++) {
|
for(i=0; i<turn_params.aux_servers_list.size; i++) {
|
||||||
|
|
||||||
@ -1494,15 +1494,15 @@ static void setup_tcp_listener_servers(ioa_engine_handle e, struct relay_server
|
|||||||
|
|
||||||
/* TCP: */
|
/* TCP: */
|
||||||
if(!turn_params.no_tcp) {
|
if(!turn_params.no_tcp) {
|
||||||
tcp_services[index] = create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], turn_params.listener_port, turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
tcp_services[index] = create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], turn_params.tcp_use_proxy?turn_params.tcp_proxy_port:turn_params.listener_port, turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
||||||
if(turn_params.rfc5780)
|
if(turn_params.rfc5780)
|
||||||
tcp_services[index+1] = create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], get_alt_listener_port(), turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
tcp_services[index+1] = turn_params.tcp_use_proxy?NULL:create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], get_alt_listener_port(), turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
||||||
} else {
|
} else {
|
||||||
tcp_services[index] = NULL;
|
tcp_services[index] = NULL;
|
||||||
if(turn_params.rfc5780)
|
if(turn_params.rfc5780)
|
||||||
tcp_services[index+1] = NULL;
|
tcp_services[index+1] = NULL;
|
||||||
}
|
}
|
||||||
if(!turn_params.no_tls && (turn_params.no_tcp || (turn_params.listener_port != turn_params.tls_listener_port))) {
|
if(!turn_params.no_tls && !turn_params.tcp_use_proxy && (turn_params.no_tcp || (turn_params.listener_port != turn_params.tls_listener_port))) {
|
||||||
tls_services[index] = create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], turn_params.tls_listener_port, turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
tls_services[index] = create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], turn_params.tls_listener_port, turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
||||||
if(turn_params.rfc5780)
|
if(turn_params.rfc5780)
|
||||||
tls_services[index+1] = create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], get_alt_tls_listener_port(), turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
tls_services[index+1] = create_tls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], get_alt_tls_listener_port(), turn_params.verbose, e, send_socket_to_general_relay, relay_server);
|
||||||
|
|||||||
@ -2157,6 +2157,67 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static ssize_t socket_parse_proxy_v2(ioa_socket_handle s, uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
if(len < 16){
|
||||||
|
return 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for proxy-v2 magic field */
|
||||||
|
char magic[] = {0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A};
|
||||||
|
if(memcmp(magic, buf, sizeof(magic))){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check version */
|
||||||
|
uint8_t version = buf[12] >> 4;
|
||||||
|
if(version != 2) return -1;
|
||||||
|
|
||||||
|
/* Read data */
|
||||||
|
uint8_t command = buf[12] & 0xF;
|
||||||
|
uint8_t family = buf[13] >> 4;
|
||||||
|
uint8_t proto = buf[13] & 0xF;
|
||||||
|
size_t plen = ((size_t)buf[14] << 8) | buf[15];
|
||||||
|
|
||||||
|
size_t tlen = 16 + plen;
|
||||||
|
if(len < tlen) return 0;
|
||||||
|
|
||||||
|
/* A local connection is used by the proxy itself and does not carry a valid address */
|
||||||
|
if(command == 0) return tlen;
|
||||||
|
|
||||||
|
/* Accept only proxied TCP connections */
|
||||||
|
if(command != 1 || proto != 1) return -1;
|
||||||
|
|
||||||
|
/* Read the address */
|
||||||
|
if(family == 1 && plen >= 12){ /* IPv4 */
|
||||||
|
struct sockaddr_in remote, local;
|
||||||
|
remote.sin_family = local.sin_family = AF_INET;
|
||||||
|
memcpy(&remote.sin_addr.s_addr, &buf[16], 4);
|
||||||
|
memcpy(&local.sin_addr.s_addr, &buf[20], 4);
|
||||||
|
memcpy(&remote.sin_port, &buf[24], 2);
|
||||||
|
memcpy(&local.sin_port, &buf[26], 2);
|
||||||
|
|
||||||
|
addr_cpy4(&(s->local_addr), &local);
|
||||||
|
addr_cpy4(&(s->remote_addr), &remote);
|
||||||
|
|
||||||
|
}else if(family == 2 && plen >= 36){ /* IPv6 */
|
||||||
|
struct sockaddr_in6 remote, local;
|
||||||
|
remote.sin6_family = local.sin6_family = AF_INET6;
|
||||||
|
memcpy(&remote.sin6_addr.s6_addr, &buf[16], 16);
|
||||||
|
memcpy(&local.sin6_addr.s6_addr, &buf[32], 16);
|
||||||
|
memcpy(&remote.sin6_port, &buf[48], 2);
|
||||||
|
memcpy(&local.sin6_port, &buf[50], 2);
|
||||||
|
|
||||||
|
addr_cpy6(&(s->local_addr), &local);
|
||||||
|
addr_cpy6(&(s->remote_addr), &remote);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlen;
|
||||||
|
}
|
||||||
|
|
||||||
static int socket_input_worker(ioa_socket_handle s)
|
static int socket_input_worker(ioa_socket_handle s)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@ -2372,12 +2433,30 @@ static int socket_input_worker(ioa_socket_handle s)
|
|||||||
struct evbuffer *inbuf = bufferevent_get_input(s->bev);
|
struct evbuffer *inbuf = bufferevent_get_input(s->bev);
|
||||||
if(inbuf) {
|
if(inbuf) {
|
||||||
ev_ssize_t blen = evbuffer_copyout(inbuf, buf_elem->buf.buf, STUN_BUFFER_SIZE);
|
ev_ssize_t blen = evbuffer_copyout(inbuf, buf_elem->buf.buf, STUN_BUFFER_SIZE);
|
||||||
|
|
||||||
if(blen>0) {
|
if(blen>0) {
|
||||||
int mlen = 0;
|
int mlen = 0;
|
||||||
|
|
||||||
if(blen>(ev_ssize_t)STUN_BUFFER_SIZE)
|
if(blen>(ev_ssize_t)STUN_BUFFER_SIZE)
|
||||||
blen=(ev_ssize_t)STUN_BUFFER_SIZE;
|
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);
|
||||||
|
blen = 0;
|
||||||
|
if (tlen < 0){
|
||||||
|
s->tobeclosed = 1;
|
||||||
|
s->broken = 1;
|
||||||
|
ret = -1;
|
||||||
|
log_socket_event(s, "proxy protocol violated",1);
|
||||||
|
}else if(tlen > 0){
|
||||||
|
bufferevent_read(s->bev, buf_elem->buf.buf, tlen);
|
||||||
|
|
||||||
|
blen = evbuffer_copyout(inbuf, buf_elem->buf.buf, STUN_BUFFER_SIZE);
|
||||||
|
s->st = TCP_SOCKET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(blen){
|
||||||
if(is_stream_socket(s->st) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) {
|
if(is_stream_socket(s->st) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) {
|
||||||
mlen = blen;
|
mlen = blen;
|
||||||
} else {
|
} else {
|
||||||
@ -2404,7 +2483,7 @@ static int socket_input_worker(ioa_socket_handle s)
|
|||||||
ret = len;
|
ret = len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if(blen<0) {
|
} else if(blen<0) {
|
||||||
s->tobeclosed = 1;
|
s->tobeclosed = 1;
|
||||||
s->broken = 1;
|
s->broken = 1;
|
||||||
@ -3277,6 +3356,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
|
|||||||
break;
|
break;
|
||||||
case SCTP_SOCKET:
|
case SCTP_SOCKET:
|
||||||
case TCP_SOCKET:
|
case TCP_SOCKET:
|
||||||
|
case TCP_SOCKET_PROXY:
|
||||||
if(s->bev) {
|
if(s->bev) {
|
||||||
if(!clean_preexisting) {
|
if(!clean_preexisting) {
|
||||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
|
||||||
|
|||||||
@ -82,7 +82,9 @@ static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd,
|
|||||||
|
|
||||||
SOCKET_TYPE st = TENTATIVE_TCP_SOCKET;
|
SOCKET_TYPE st = TENTATIVE_TCP_SOCKET;
|
||||||
|
|
||||||
if(turn_params.no_tls)
|
if(turn_params.tcp_use_proxy)
|
||||||
|
st = TCP_SOCKET_PROXY;
|
||||||
|
else if(turn_params.no_tls)
|
||||||
st = TCP_SOCKET;
|
st = TCP_SOCKET;
|
||||||
else if(turn_params.no_tcp)
|
else if(turn_params.no_tcp)
|
||||||
st = TLS_SOCKET;
|
st = TLS_SOCKET;
|
||||||
|
|||||||
@ -90,6 +90,7 @@ enum _SOCKET_TYPE {
|
|||||||
SCTP_SOCKET=132,
|
SCTP_SOCKET=132,
|
||||||
TLS_SCTP_SOCKET=133,
|
TLS_SCTP_SOCKET=133,
|
||||||
DTLS_SOCKET=250,
|
DTLS_SOCKET=250,
|
||||||
|
TCP_SOCKET_PROXY=253,
|
||||||
TENTATIVE_SCTP_SOCKET=254,
|
TENTATIVE_SCTP_SOCKET=254,
|
||||||
TENTATIVE_TCP_SOCKET=255
|
TENTATIVE_TCP_SOCKET=255
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user