mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-21 14:33:55 +00:00
ss-redir: allow you to define additionals listenings ports to set a TOS/DSCP on the outgoings ciphered connections
This commit is contained in:
committed by
Max Lv
parent
8d2918b5cb
commit
51afa5e548
+52
@@ -109,6 +109,41 @@ parse_addr(const char *str_in, ss_addr_t *addr)
|
||||
free(str);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_dscp(char *str)
|
||||
{
|
||||
size_t str_len = strlen(str);
|
||||
|
||||
// Pre-defined values (EF, CSx, AFxy)
|
||||
if (str_len == 2 && strcasecmp(str, "EF") == 0) {
|
||||
return DSCP_EF;
|
||||
}
|
||||
|
||||
if (str_len == DSCP_CS_LEN && strncasecmp(str, "CS", 2) == 0) {
|
||||
if (str[2] >= '0' && str[2] <= '7') {
|
||||
// CSx = 8x
|
||||
return (str[2] - '0') << 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (str_len == DSCP_AF_LEN && strncasecmp(str, "AF", 2) == 0) {
|
||||
if (str[2] >= '1' && str[2] <= '4' && str[3] >= '1' && str[3] <= '3') {
|
||||
// AFxy = 8x + 2y
|
||||
return ((str[2] - '0') << 3) | ((str[3] - '0') << 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Manual hexadecimal mode (0xYZ)
|
||||
char *endptr;
|
||||
int dscp = (int)strtol(str, &endptr, 0);
|
||||
if (*endptr == '\0' && dscp >= DSCP_MIN && dscp <= DSCP_MAX) {
|
||||
return dscp;
|
||||
}
|
||||
|
||||
LOGE("Invalid DSCP value (%s)", str);
|
||||
return DSCP_DEFAULT;
|
||||
}
|
||||
|
||||
jconf_t *
|
||||
read_jconf(const char *file)
|
||||
{
|
||||
@@ -230,6 +265,23 @@ read_jconf(const char *file)
|
||||
conf.nofile = value->u.integer;
|
||||
} else if (strcmp(name, "nameserver") == 0) {
|
||||
conf.nameserver = to_string(value);
|
||||
} else if (strcmp(name, "dscp") == 0) {
|
||||
if (value->type == json_object) {
|
||||
for (j = 0; j < value->u.object.length; j++) {
|
||||
if (j >= MAX_DSCP_NUM) {
|
||||
break;
|
||||
}
|
||||
json_value *v = value->u.object.values[j].value;
|
||||
if (v->type == json_string) {
|
||||
int dscp = parse_dscp(to_string(v));
|
||||
char *port = ss_strndup(value->u.object.values[j].name,
|
||||
value->u.object.values[j].name_length);
|
||||
conf.dscp[j].port = port;
|
||||
conf.dscp[j].dscp = dscp;
|
||||
conf.dscp_num = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (strcmp(name, "tunnel_address") == 0) {
|
||||
conf.tunnel_address = to_string(value);
|
||||
} else if (strcmp(name, "mode") == 0) {
|
||||
|
||||
+17
@@ -24,12 +24,22 @@
|
||||
|
||||
#define MAX_PORT_NUM 1024
|
||||
#define MAX_REMOTE_NUM 10
|
||||
#define MAX_DSCP_NUM 64
|
||||
#define MAX_CONF_SIZE 128 * 1024
|
||||
#define MAX_DNS_NUM 4
|
||||
#define MAX_CONNECT_TIMEOUT 10
|
||||
#define MAX_REQUEST_TIMEOUT 60
|
||||
#define MIN_UDP_TIMEOUT 10
|
||||
|
||||
#define DSCP_EF 0x2E
|
||||
#define DSCP_MIN 0x0
|
||||
#define DSCP_MAX 0x3F
|
||||
#define DSCP_DEFAULT 0x0
|
||||
#define DSCP_MIN_LEN 2
|
||||
#define DSCP_MAX_LEN 4
|
||||
#define DSCP_CS_LEN 3
|
||||
#define DSCP_AF_LEN 4
|
||||
|
||||
#define TCP_ONLY 0
|
||||
#define TCP_AND_UDP 1
|
||||
#define UDP_ONLY 3
|
||||
@@ -44,6 +54,11 @@ typedef struct {
|
||||
char *password;
|
||||
} ss_port_password_t;
|
||||
|
||||
typedef struct {
|
||||
char *port;
|
||||
int dscp;
|
||||
} ss_dscp_t;
|
||||
|
||||
typedef struct {
|
||||
int remote_num;
|
||||
ss_addr_t remote_addr[MAX_REMOTE_NUM];
|
||||
@@ -63,6 +78,8 @@ typedef struct {
|
||||
int reuse_port;
|
||||
int nofile;
|
||||
char *nameserver;
|
||||
int dscp_num;
|
||||
ss_dscp_t dscp[MAX_DSCP_NUM];
|
||||
char *tunnel_address;
|
||||
int mode;
|
||||
int mtu;
|
||||
|
||||
+58
-32
@@ -786,6 +786,12 @@ accept_cb(EV_P_ ev_io *w, int revents)
|
||||
// Set non blocking
|
||||
setnonblocking(remotefd);
|
||||
|
||||
if (listener->tos >= 0) {
|
||||
if (setsockopt(remotefd, IPPROTO_IP, IP_TOS, &listener->tos, sizeof(listener->tos)) != 0) {
|
||||
ERROR("setsockopt IP_TOS");
|
||||
}
|
||||
}
|
||||
|
||||
// Enable MPTCP
|
||||
if (listener->mptcp > 1) {
|
||||
int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));
|
||||
@@ -883,6 +889,9 @@ main(int argc, char **argv)
|
||||
ss_addr_t remote_addr[MAX_REMOTE_NUM];
|
||||
char *remote_port = NULL;
|
||||
|
||||
int dscp_num = 0;
|
||||
ss_dscp_t * dscp = NULL;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "fast-open", no_argument, NULL, GETOPT_VAL_FAST_OPEN },
|
||||
{ "mtu", required_argument, NULL, GETOPT_VAL_MTU },
|
||||
@@ -1061,6 +1070,8 @@ main(int argc, char **argv)
|
||||
nofile = conf->nofile;
|
||||
}
|
||||
#endif
|
||||
dscp_num = conf->dscp_num;
|
||||
dscp = conf->dscp;
|
||||
}
|
||||
|
||||
if (remote_num == 0 || remote_port == NULL || local_port == NULL
|
||||
@@ -1187,44 +1198,59 @@ main(int argc, char **argv)
|
||||
|
||||
struct ev_loop *loop = EV_DEFAULT;
|
||||
|
||||
if (mode != UDP_ONLY) {
|
||||
// Setup socket
|
||||
int listenfd;
|
||||
listenfd = create_and_bind(local_addr, local_port);
|
||||
if (listenfd == -1) {
|
||||
FATAL("bind() error");
|
||||
listen_ctx_t* listen_ctx_current = &listen_ctx;
|
||||
do {
|
||||
if (mode != UDP_ONLY) {
|
||||
// Setup socket
|
||||
int listenfd;
|
||||
listenfd = create_and_bind(local_addr, local_port);
|
||||
if (listenfd == -1) {
|
||||
FATAL("bind() error");
|
||||
}
|
||||
if (listen(listenfd, SOMAXCONN) == -1) {
|
||||
FATAL("listen() error");
|
||||
}
|
||||
setnonblocking(listenfd);
|
||||
|
||||
listen_ctx_current->fd = listenfd;
|
||||
|
||||
ev_io_init(&listen_ctx_current->io, accept_cb, listenfd, EV_READ);
|
||||
ev_io_start(loop, &listen_ctx_current->io);
|
||||
}
|
||||
if (listen(listenfd, SOMAXCONN) == -1) {
|
||||
FATAL("listen() error");
|
||||
|
||||
// Setup UDP
|
||||
if (mode != TCP_ONLY) {
|
||||
LOGI("UDP relay enabled");
|
||||
char *host = remote_addr[0].host;
|
||||
char *port = remote_addr[0].port == NULL ? remote_port : remote_addr[0].port;
|
||||
struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));
|
||||
memset(storage, 0, sizeof(struct sockaddr_storage));
|
||||
if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {
|
||||
FATAL("failed to resolve the provided hostname");
|
||||
}
|
||||
struct sockaddr *addr = (struct sockaddr *)storage;
|
||||
init_udprelay(local_addr, local_port, addr,
|
||||
get_sockaddr_len(addr), mtu, crypto, listen_ctx_current->timeout, NULL);
|
||||
}
|
||||
setnonblocking(listenfd);
|
||||
|
||||
listen_ctx.fd = listenfd;
|
||||
|
||||
ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
|
||||
ev_io_start(loop, &listen_ctx.io);
|
||||
}
|
||||
|
||||
// Setup UDP
|
||||
if (mode != TCP_ONLY) {
|
||||
LOGI("UDP relay enabled");
|
||||
char *host = remote_addr[0].host;
|
||||
char *port = remote_addr[0].port == NULL ? remote_port : remote_addr[0].port;
|
||||
struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));
|
||||
memset(storage, 0, sizeof(struct sockaddr_storage));
|
||||
if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {
|
||||
FATAL("failed to resolve the provided hostname");
|
||||
if (mode == UDP_ONLY) {
|
||||
LOGI("TCP relay disabled");
|
||||
}
|
||||
struct sockaddr *addr = (struct sockaddr *)storage;
|
||||
init_udprelay(local_addr, local_port, addr,
|
||||
get_sockaddr_len(addr), mtu, crypto, listen_ctx.timeout, NULL);
|
||||
}
|
||||
|
||||
if (mode == UDP_ONLY) {
|
||||
LOGI("TCP relay disabled");
|
||||
}
|
||||
if(listen_ctx_current->tos) {
|
||||
LOGI("listening at %s:%s (TOS/DSCP 0x%x)", local_addr, local_port, listen_ctx_current->tos);
|
||||
} else {
|
||||
LOGI("listening at %s:%s", local_addr, local_port);
|
||||
}
|
||||
|
||||
LOGI("listening at %s:%s", local_addr, local_port);
|
||||
// Handle additionals TOS/DSCP listening ports
|
||||
if (dscp_num > 0) {
|
||||
listen_ctx_current = (listen_ctx_t*) malloc(sizeof(listen_ctx_t));
|
||||
listen_ctx_current = memcpy(listen_ctx_current, &listen_ctx, sizeof(listen_ctx_t));
|
||||
local_port = dscp[dscp_num-1].port;
|
||||
listen_ctx_current->tos = dscp[dscp_num-1].dscp;
|
||||
}
|
||||
} while (dscp_num-- > 0);
|
||||
|
||||
// setuid
|
||||
if (user != NULL && !run_as(user)) {
|
||||
|
||||
@@ -37,6 +37,7 @@ typedef struct listen_ctx {
|
||||
int timeout;
|
||||
int fd;
|
||||
int mptcp;
|
||||
int tos;
|
||||
struct sockaddr **remote_addr;
|
||||
} listen_ctx_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user