mirror of
https://github.com/coturn/coturn.git
synced 2025-11-01 07:21:04 +01:00
Merge pull request #479 from WaxieSDR/master
Add support for reverse proxy connections
This commit is contained in:
commit
db68c76195
@ -321,6 +321,10 @@ Options with values:
|
||||
|
||||
--alt-tls-listening-port Alternative listening port for TLS and DTLS protocols.
|
||||
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 servers have almost full TURN and STUN functionality.
|
||||
|
||||
@ -44,6 +44,14 @@
|
||||
# Default (or zero) value means "TLS listening port plus one".
|
||||
#
|
||||
#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.
|
||||
# If no IP(s) specified in the config file or in the command line options,
|
||||
|
||||
@ -481,6 +481,12 @@ Alternative listening port for TLS and DTLS protocols.
|
||||
Default (or zero) value means "TLS listening port plus one".
|
||||
.TP
|
||||
.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
|
||||
Auxiliary STUN/TURN server listening endpoint.
|
||||
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) {
|
||||
switch(st) {
|
||||
case TCP_SOCKET:
|
||||
case TCP_SOCKET_PROXY:
|
||||
case TLS_SOCKET:
|
||||
case TENTATIVE_TCP_SOCKET:
|
||||
case SCTP_SOCKET:
|
||||
|
||||
@ -110,8 +110,8 @@ NULL, PTHREAD_MUTEX_INITIALIZER,
|
||||
//////////////// Common params ////////////////////
|
||||
TURN_VERBOSE_NONE,0,0,0,0,
|
||||
"/var/run/turnserver.pid",
|
||||
DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1,
|
||||
0,0,0,0,
|
||||
DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,0,1,
|
||||
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"
|
||||
" --alt-tls-listening-port <port> Alternative listening port for TLS and DTLS,\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"
|
||||
" --aux-server <ip:port> Auxiliary STUN/TURN server listening endpoint.\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 {
|
||||
NO_UDP_OPT=256,
|
||||
NO_TCP_OPT,
|
||||
TCP_PROXY_PORT_OPT,
|
||||
NO_TLS_OPT,
|
||||
NO_DTLS_OPT,
|
||||
NO_UDP_RELAY_OPT,
|
||||
@ -805,6 +808,7 @@ static const struct myoption long_options[] = {
|
||||
{ "tls-listening-port", required_argument, NULL, TLS_PORT_OPT },
|
||||
{ "alt-listening-port", required_argument, NULL, ALT_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' },
|
||||
{ "relay-device", required_argument, NULL, 'i' },
|
||||
{ "relay-ip", required_argument, NULL, 'E' },
|
||||
@ -1267,6 +1271,10 @@ static void set_option(int c, char *value)
|
||||
case ALT_TLS_PORT_OPT:
|
||||
turn_params.alt_tls_listener_port = atoi(value);
|
||||
break;
|
||||
case TCP_PROXY_PORT_OPT:
|
||||
turn_params.tcp_proxy_port = atoi(value);
|
||||
turn_params.tcp_use_proxy = 1;
|
||||
break;
|
||||
case MIN_PORT_OPT:
|
||||
turn_params.min_port = atoi(value);
|
||||
break;
|
||||
|
||||
@ -226,10 +226,12 @@ typedef struct _turn_params_ {
|
||||
int tls_listener_port;
|
||||
int alt_listener_port;
|
||||
int alt_tls_listener_port;
|
||||
int tcp_proxy_port;
|
||||
int rfc5780;
|
||||
|
||||
int no_udp;
|
||||
int no_tcp;
|
||||
int tcp_use_proxy;
|
||||
|
||||
vint no_tcp_relay;
|
||||
vint no_udp_relay;
|
||||
|
||||
@ -1473,7 +1473,7 @@ static void setup_tcp_listener_servers(ioa_engine_handle e, struct relay_server
|
||||
/* Create listeners */
|
||||
|
||||
/* 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++) {
|
||||
|
||||
@ -1494,15 +1494,15 @@ static void setup_tcp_listener_servers(ioa_engine_handle e, struct relay_server
|
||||
|
||||
/* 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)
|
||||
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 {
|
||||
tcp_services[index] = NULL;
|
||||
if(turn_params.rfc5780)
|
||||
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);
|
||||
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);
|
||||
|
||||
@ -2157,6 +2157,67 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd)
|
||||
}
|
||||
#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)
|
||||
{
|
||||
int len = 0;
|
||||
@ -2372,39 +2433,57 @@ static int socket_input_worker(ioa_socket_handle s)
|
||||
struct evbuffer *inbuf = bufferevent_get_input(s->bev);
|
||||
if(inbuf) {
|
||||
ev_ssize_t blen = evbuffer_copyout(inbuf, buf_elem->buf.buf, STUN_BUFFER_SIZE);
|
||||
|
||||
if(blen>0) {
|
||||
int mlen = 0;
|
||||
|
||||
if(blen>(ev_ssize_t)STUN_BUFFER_SIZE)
|
||||
blen=(ev_ssize_t)STUN_BUFFER_SIZE;
|
||||
|
||||
if(is_stream_socket(s->st) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) {
|
||||
mlen = blen;
|
||||
} else {
|
||||
mlen = stun_get_message_len_str(buf_elem->buf.buf, blen, 1, &app_msg_len);
|
||||
}
|
||||
|
||||
if(mlen>0 && mlen<=(int)blen) {
|
||||
len = (int)bufferevent_read(s->bev, buf_elem->buf.buf, mlen);
|
||||
if(len < 0) {
|
||||
ret = -1;
|
||||
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;
|
||||
log_socket_event(s, "socket read failed, to be closed",1);
|
||||
} else if((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) {
|
||||
#if TLS_SUPPORTED
|
||||
SSL *ctx = bufferevent_openssl_get_ssl(s->bev);
|
||||
if(!ctx || SSL_get_shutdown(ctx)) {
|
||||
ret = -1;
|
||||
s->tobeclosed = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if(ret != -1) {
|
||||
ret = len;
|
||||
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))) {
|
||||
mlen = blen;
|
||||
} else {
|
||||
mlen = stun_get_message_len_str(buf_elem->buf.buf, blen, 1, &app_msg_len);
|
||||
}
|
||||
|
||||
if(mlen>0 && mlen<=(int)blen) {
|
||||
len = (int)bufferevent_read(s->bev, buf_elem->buf.buf, mlen);
|
||||
if(len < 0) {
|
||||
ret = -1;
|
||||
s->tobeclosed = 1;
|
||||
s->broken = 1;
|
||||
log_socket_event(s, "socket read failed, to be closed",1);
|
||||
} else if((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) {
|
||||
#if TLS_SUPPORTED
|
||||
SSL *ctx = bufferevent_openssl_get_ssl(s->bev);
|
||||
if(!ctx || SSL_get_shutdown(ctx)) {
|
||||
ret = -1;
|
||||
s->tobeclosed = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if(ret != -1) {
|
||||
ret = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(blen<0) {
|
||||
s->tobeclosed = 1;
|
||||
s->broken = 1;
|
||||
@ -3277,6 +3356,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
|
||||
break;
|
||||
case SCTP_SOCKET:
|
||||
case TCP_SOCKET:
|
||||
case TCP_SOCKET_PROXY:
|
||||
if(s->bev) {
|
||||
if(!clean_preexisting) {
|
||||
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;
|
||||
|
||||
if(turn_params.no_tls)
|
||||
if(turn_params.tcp_use_proxy)
|
||||
st = TCP_SOCKET_PROXY;
|
||||
else if(turn_params.no_tls)
|
||||
st = TCP_SOCKET;
|
||||
else if(turn_params.no_tcp)
|
||||
st = TLS_SOCKET;
|
||||
|
||||
@ -90,6 +90,7 @@ enum _SOCKET_TYPE {
|
||||
SCTP_SOCKET=132,
|
||||
TLS_SCTP_SOCKET=133,
|
||||
DTLS_SOCKET=250,
|
||||
TCP_SOCKET_PROXY=253,
|
||||
TENTATIVE_SCTP_SOCKET=254,
|
||||
TENTATIVE_TCP_SOCKET=255
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user