Added support for no-routes (X-Split-Exclude)

This commit is contained in:
Nikos Mavrogiannopoulos
2015-02-06 14:02:34 +01:00
parent 5f34edaf31
commit bcea928abe
15 changed files with 150 additions and 52 deletions

View File

@@ -342,10 +342,15 @@ ping-leases = false
# comment out all routes from the server, or use the special keyword
# 'default'.
route = 192.168.1.0/255.255.255.0
route = 192.168.5.0/255.255.255.0
route = 10.10.10.0/255.255.255.0
route = 192.168.0.0/255.255.0.0
#route = fef4:db8:1000:1001::/64
# Subsets of the routes above that will not be routed by
# the server.
no-route = 192.168.5.0/255.255.255.0
# Groups that a client is allowed to select from.
# A client may belong in multiple groups, and in certain use-cases
# it is needed to switch between them. For these cases the client can

View File

@@ -59,6 +59,7 @@ struct cfg_options {
static struct cfg_options available_options[] = {
{ .name = "auth", .type = OPTION_MULTI_LINE, .mandatory = 1 },
{ .name = "route", .type = OPTION_MULTI_LINE, .mandatory = 0 },
{ .name = "no-route", .type = OPTION_MULTI_LINE, .mandatory = 0 },
{ .name = "select-group", .type = OPTION_MULTI_LINE, .mandatory = 0 },
{ .name = "custom-header", .type = OPTION_MULTI_LINE, .mandatory = 0 },
{ .name = "split-dns", .type = OPTION_MULTI_LINE, .mandatory = 0 },
@@ -723,6 +724,8 @@ unsigned force_cert_auth;
}
}
READ_MULTI_LINE("no-route", config->network.no_routes, config->network.no_routes_size);
READ_STRING("default-select-group", config->default_select_group);
READ_TF("auto-select-group", auto_select_group, 0);
if (auto_select_group != 0 && amod != NULL && amod->group_list != NULL) {

View File

@@ -43,6 +43,7 @@ message user_info_rep
optional string cstp_compr = 23;
optional string dtls_compr = 24;
repeated string no_routes = 25;
}
message user_list_rep

View File

@@ -1,3 +1,29 @@
/* === Authentication ===
main sec-mod worker
| | |
| | <--AUTH_INIT--- |
| | ---AUTH_REP---> |
| | <--AUTH_CONT--- |
| | . |
| | . |
| | . |
| | ----AUTH_REP--> |
| | |
| <----------AUTH_COOKIE_REQ------------- |
| | |
| ---SESSION_OPEN----> | |
| <--SESSION_REPLY---- | |
| | |
| -----------------AUTH_REP-------------> |
| | |
| |
| | (disconnect)
| ---SESSION_CLOSE---> |
*/
/*
* == Auth in main process (cookie auth only) ==
*
@@ -50,6 +76,7 @@ message auth_reply_msg
optional string xml_config_file = 26;
optional string ipv4_network = 27;
optional string ipv6_network = 28;
repeated string no_routes = 29;
}
/* RESUME_FETCH_REQ + RESUME_DELETE_REQ */
@@ -185,7 +212,7 @@ message cookie
*
* main sec-mod
* SESSION_OPEN/CLOSE ------>
*
* <------ SESSION_REPLY
*/
/* SEC_SESSION_CLOSE */
@@ -221,4 +248,5 @@ message sec_auth_session_reply_msg
optional uint32 net_priority = 25;
optional string explicit_ipv4 = 26;
optional string explicit_ipv6 = 27;
repeated string no_routes = 28;
}

View File

@@ -131,6 +131,12 @@ int send_cookie_auth_reply(main_server_st* s, struct proc_st* proc,
msg.routes = proc->config.routes;
}
msg.n_no_routes = proc->config.no_routes_size;
for (i=0;i<proc->config.no_routes_size;i++) {
mslog(s, proc, LOG_DEBUG, "sending no-route '%s'", proc->config.no_routes[i]);
msg.no_routes = proc->config.no_routes;
}
ret = send_socket_msg_to_worker(s, proc, AUTH_COOKIE_REP, proc->tun_lease.fd,
&msg,
(pack_size_func)auth_reply_msg__get_packed_size,

View File

@@ -376,6 +376,14 @@ static int append_user_info(method_ctx *ctx,
rep->n_routes = ctx->s->config->network.routes_size;
}
if (ctmp->config.no_routes_size > 0) {
rep->no_routes = ctmp->config.no_routes;
rep->n_no_routes = ctmp->config.no_routes_size;
} else {
rep->no_routes = ctx->s->config->network.no_routes;
rep->n_no_routes = ctx->s->config->network.no_routes_size;
}
if (ctmp->config.iroutes_size > 0) {
rep->iroutes = ctmp->config.iroutes;
rep->n_iroutes = ctmp->config.iroutes_size;

View File

@@ -287,6 +287,14 @@ int session_cmd(main_server_st * s, struct proc_st *proc, unsigned open)
proc->config.routes_size = msg->n_routes;
}
if (msg->n_no_routes > 0) {
proc->config.no_routes = talloc_size(proc, sizeof(char*)*msg->n_no_routes);
for (i=0;i<msg->n_no_routes;i++) {
proc->config.no_routes[i] = talloc_strdup(proc, msg->no_routes[i]);
}
proc->config.no_routes_size = msg->n_no_routes;
}
if (msg->n_iroutes > 0) {
proc->config.iroutes = talloc_size(proc, sizeof(char*)*msg->n_iroutes);
for (i=0;i<msg->n_iroutes;i++) {

View File

@@ -658,6 +658,9 @@ int common_info_cmd(UserListRep * args)
fprintf(out, "Routes: defaultroute\n");
}
if ((r = print_list_entries(out, "\tNo-routes:", args->user[i]->no_routes, args->user[i]->n_no_routes)) < 0)
goto error_parse;
if (print_list_entries(out, "\tiRoutes:", args->user[i]->iroutes, args->user[i]->n_iroutes) < 0)
goto error_parse;

View File

@@ -417,10 +417,15 @@ ping-leases = false
# comment out all routes from the server, or use the special keyword
# 'default'.
route = 192.168.1.0/255.255.255.0
route = 192.168.5.0/255.255.255.0
route = 10.10.10.0/255.255.255.0
route = 192.168.0.0/255.255.0.0
#route = fef4:db8:1000:1001::/64
# Subsets of the routes above that will not be routed by
# the server.
no-route = 192.168.5.0/255.255.255.0
# Groups that a client is allowed to select from.
# A client may belong in multiple groups, and in certain use-cases
# it is needed to switch between them. For these cases the client can
@@ -441,7 +446,7 @@ route = 192.168.5.0/255.255.255.0
# per group. Each file name on these directories must match the username
# or the groupname.
# The options allowed in the configuration files are dns, nbns,
# ipv?-network, ipv4-netmask, rx/tx-per-sec, iroute, route,
# ipv?-network, ipv4-netmask, rx/tx-per-sec, iroute, route, no-route,
# net-priority, deny-roaming, no-udp, user-profile, require-cert, and cgroup.
#
# Note that the 'iroute' option allows to add routes on the server

View File

@@ -46,6 +46,7 @@ static struct cfg_options available_options[] = {
{ .name = "deny-roaming", .type = OPTION_BOOLEAN },
{ .name = "require-cert", .type = OPTION_BOOLEAN },
{ .name = "route", .type = OPTION_MULTI_LINE },
{ .name = "no-route", .type = OPTION_MULTI_LINE },
{ .name = "iroute", .type = OPTION_MULTI_LINE },
{ .name = "dns", .type = OPTION_MULTI_LINE },
{ .name = "ipv4-dns", .type = OPTION_MULTI_LINE }, /* alias of dns */
@@ -183,6 +184,7 @@ unsigned prefix = 0;
READ_TF("require-cert", msg->require_cert, msg->has_require_cert);
READ_RAW_MULTI_LINE("route", msg->routes, msg->n_routes);
READ_RAW_MULTI_LINE("no-route", msg->no_routes, msg->n_no_routes);
READ_RAW_MULTI_LINE("iroute", msg->iroutes, msg->n_iroutes);
READ_RAW_MULTI_LINE("dns", msg->dns, msg->n_dns);

View File

@@ -147,6 +147,10 @@ struct group_cfg_st {
char **routes;
unsigned int routes_size;
/* routes that are excluded */
char **no_routes;
unsigned int no_routes_size;
/* routes to be applied to the server */
char **iroutes;
unsigned int iroutes_size;
@@ -194,6 +198,10 @@ struct vpn_st {
char **routes;
unsigned int routes_size;
/* excluded routes */
char **no_routes;
unsigned int no_routes_size;
char **dns;
unsigned int dns_size;

View File

@@ -602,6 +602,15 @@ static int recv_cookie_auth_reply(worker_st * ws)
if (check_if_default_route(ws->routes, ws->routes_size))
ws->default_route = 1;
ws->no_routes = talloc_size(ws, msg->n_no_routes*sizeof(char*));
if (ws->no_routes != NULL) {
ws->no_routes_size = msg->n_no_routes;
for (i = 0; i < ws->no_routes_size; i++) {
ws->no_routes[i] =
talloc_strdup(ws, msg->no_routes[i]);
}
}
ws->dns = talloc_size(ws, msg->n_dns*sizeof(char*));
if (ws->dns != NULL) {
ws->dns_size = msg->n_dns;

View File

@@ -227,6 +227,10 @@ int complete_vpn_info(worker_st * ws, struct vpn_st *vinfo)
if (check_if_default_route(vinfo->routes, vinfo->routes_size))
ws->default_route = 1;
vinfo->no_routes_size = ws->config->network.no_routes_size;
if (ws->config->network.no_routes_size > 0)
vinfo->no_routes = ws->config->network.no_routes;
vinfo->ipv4_network = ws->config->network.ipv4_network;
vinfo->ipv6_network = ws->config->network.ipv6_network;

View File

@@ -1092,6 +1092,47 @@ char *replace_vals(worker_st *ws, const char *txt)
return (char*)str.data;
}
static int send_routes(worker_st *ws, struct http_req_st *req,
char **routes, unsigned routes_size,
bool include)
{
unsigned i;
unsigned ip6;
const char *txt;
int ret;
if (include)
txt = "Include";
else
txt = "Exclude";
for (i = 0; i < routes_size; i++) {
if (strchr(routes[i], ':') != 0)
ip6 = 1;
else
ip6 = 0;
if (req->no_ipv6 != 0 && ip6 != 0)
continue;
if (req->no_ipv4 != 0 && ip6 == 0)
continue;
oclog(ws, LOG_DEBUG, "%s route %s", txt, routes[i]);
if (ip6 != 0 && ws->full_ipv6) {
ret = cstp_printf(ws,
"X-CSTP-Split-%s-IP6: %s\r\n",
txt, routes[i]);
} else {
ret = cstp_printf(ws,
"X-CSTP-Split-%s: %s\r\n",
txt, routes[i]);
}
if (ret < 0)
return ret;
}
return 0;
}
/* connect_handler:
* @ws: an initialized worker structure
*
@@ -1377,54 +1418,18 @@ static int connect_handler(worker_st * ws)
}
if (ws->default_route == 0) {
for (i = 0; i < ws->vinfo.routes_size; i++) {
if (strchr(ws->vinfo.routes[i], ':') != 0)
ip6 = 1;
else
ip6 = 0;
ret = send_routes(ws, req, ws->vinfo.routes, ws->vinfo.routes_size, 1);
SEND_ERR(ret);
if (req->no_ipv6 != 0 && ip6 != 0)
continue;
if (req->no_ipv4 != 0 && ip6 == 0)
continue;
oclog(ws, LOG_DEBUG, "adding route %s", ws->vinfo.routes[i]);
if (ip6 != 0 && ws->full_ipv6) {
ret = cstp_printf(ws,
"X-CSTP-Split-Include-IP6: %s\r\n",
ws->vinfo.routes[i]);
} else {
ret = cstp_printf(ws,
"X-CSTP-Split-Include: %s\r\n",
ws->vinfo.routes[i]);
}
ret = send_routes(ws, req, ws->routes, ws->routes_size, 1);
SEND_ERR(ret);
}
for (i = 0; i < ws->routes_size; i++) {
if (strchr(ws->routes[i], ':') != 0)
ip6 = 1;
else
ip6 = 0;
if (req->no_ipv6 != 0 && ip6 != 0)
continue;
if (req->no_ipv4 != 0 && ip6 == 0)
continue;
oclog(ws, LOG_DEBUG, "adding private route %s", ws->routes[i]);
if (ip6 != 0 && ws->full_ipv6) {
ret = cstp_printf(ws,
"X-CSTP-Split-Include-IP6: %s\r\n",
ws->routes[i]);
} else {
ret = cstp_printf(ws,
"X-CSTP-Split-Include: %s\r\n",
ws->routes[i]);
}
ret = send_routes(ws, req, ws->vinfo.no_routes, ws->vinfo.no_routes_size, 0);
SEND_ERR(ret);
ret = send_routes(ws, req, ws->no_routes, ws->no_routes_size, 0);
SEND_ERR(ret);
}
}
ret =
cstp_printf(ws, "X-CSTP-Keepalive: %u\r\n",

View File

@@ -245,6 +245,9 @@ typedef struct worker_st {
/* additional data - received per user or per group */
unsigned routes_size;
char** routes;
unsigned no_routes_size;
char** no_routes;
unsigned dns_size;
char** dns;
unsigned nbns_size;