Merge pull request #114 from feiskyer/pm

Add external network white list for port mapping
This commit is contained in:
Gao feng
2016-06-03 16:42:07 +08:00
3 changed files with 206 additions and 56 deletions
+8 -2
View File
@@ -49,8 +49,8 @@ struct hyper_pod {
struct hyper_container *c;
struct hyper_interface *iface;
struct hyper_route *rt;
struct portmapping_white_list *portmap_white_lists;
char **dns;
char **white_cidrs;
struct list_head containers;
struct list_head exec_head;
char *hostname;
@@ -60,7 +60,6 @@ struct hyper_pod {
uint32_t r_num;
uint32_t e_num;
uint32_t d_num;
uint32_t w_num;
uint32_t type;
/* how many containers are running */
uint32_t remains;
@@ -68,6 +67,13 @@ struct hyper_pod {
int efd;
};
struct portmapping_white_list {
char **internal_networks;
char **external_networks;
uint32_t i_num;
uint32_t e_num;
};
struct hyper_win_size {
char *tty;
int row;
+99 -13
View File
@@ -997,14 +997,14 @@ static int hyper_parse_dns(struct hyper_pod *pod, char *json, jsmntok_t *toks)
i++;
for (j = 0; j < pod->d_num; j++, i++) {
pod->dns[j] = (json_token_str(json, &toks[i]));
pod->dns[j] = json_token_str(json, &toks[i]);
fprintf(stdout, "pod dns %d: %s\n", j, pod->dns[j]);
}
return i;
}
static int hyper_parse_white_cidrs(struct hyper_pod *pod, char *json, jsmntok_t *toks)
static int hyper_parse_portmapping_internal_networks(struct portmapping_white_list *podmapping, char *json, jsmntok_t *toks)
{
int i = 0, j;
@@ -1013,28 +1013,114 @@ static int hyper_parse_white_cidrs(struct hyper_pod *pod, char *json, jsmntok_t
}
if (toks[i].type != JSMN_ARRAY) {
fprintf(stdout, "white CIDRs format incorrect\n");
fprintf(stdout, "internal networks format incorrect\n");
return -1;
}
pod->w_num = toks[i].size;
fprintf(stdout, "white CIDRs count %d\n", pod->w_num);
podmapping->i_num = toks[i].size;
fprintf(stdout, "internal networks count %d\n", podmapping->i_num);
pod->white_cidrs = calloc(pod->w_num, sizeof(*pod->white_cidrs));
if (pod->white_cidrs == NULL) {
fprintf(stdout, "alloc memory for white_cidrs failed\n");
podmapping->internal_networks = calloc(podmapping->i_num, sizeof(*podmapping->internal_networks));
if (podmapping->internal_networks == NULL) {
fprintf(stdout, "alloc memory for internal_networks failed\n");
return -1;
}
i++;
for (j = 0; j < pod->w_num; j++, i++) {
pod->white_cidrs[j] = (json_token_str(json, &toks[i]));
fprintf(stdout, "pod white_cidr %d: %s\n", j, pod->white_cidrs[j]);
for (j = 0; j < podmapping->i_num; j++, i++) {
podmapping->internal_networks[j] = json_token_str(json, &toks[i]);
fprintf(stdout, "podmapping internal_networks %d: %s\n", j, podmapping->internal_networks[j]);
}
return i;
}
static int hyper_parse_portmapping_external_networks(struct portmapping_white_list *podmapping, char *json, jsmntok_t *toks)
{
int i = 0, j;
if (toks[i].size == 0) {
return 0;
}
if (toks[i].type != JSMN_ARRAY) {
fprintf(stdout, "external networks format incorrect\n");
return -1;
}
podmapping->e_num = toks[i].size;
fprintf(stdout, "external networks count %d\n", podmapping->e_num);
podmapping->external_networks = calloc(podmapping->e_num, sizeof(*podmapping->external_networks));
if (podmapping->external_networks == NULL) {
fprintf(stdout, "alloc memory for external_networks failed\n");
return -1;
}
i++;
for (j = 0; j < podmapping->e_num; j++, i++) {
podmapping->external_networks[j] = json_token_str(json, &toks[i]);
fprintf(stdout, "podmapping external_networks %d: %s\n", j, podmapping->external_networks[j]);
}
return i;
}
static int hyper_parse_portmapping_whitelist(struct hyper_pod *pod, char *json, jsmntok_t *toks)
{
int i = 0, j, toks_size, next;
if (toks[i].type != JSMN_OBJECT) {
fprintf(stdout, "PortmappingWhiteLists format incorrect\n");
return -1;
}
pod->portmap_white_lists = calloc(1, sizeof(*pod->portmap_white_lists));
if (pod->portmap_white_lists == NULL) {
fprintf(stdout, "alloc memory for portmap_white_lists failed\n");
return -1;
}
toks_size = toks[i].size;
i++;
for (j = 0; j < toks_size; j++) {
jsmntok_t *t = &toks[i];
fprintf(stdout, "token %d, type is %d, size is %d\n", i, t->type, t->size);
if (t->type != JSMN_STRING) {
i++;
continue;
}
if (json_token_streq(json, t, "internalNetworks") && t->size == 1) {
next = hyper_parse_portmapping_internal_networks(pod->portmap_white_lists, json, &toks[++i]);
if (next < -1) {
goto out;
}
i += next;
} else if (json_token_streq(json, t, "externalNetworks") && t->size == 1) {
next = hyper_parse_portmapping_external_networks(pod->portmap_white_lists, json, &toks[++i]);
if (next < -1) {
goto out;
}
i += next;
} else {
fprintf(stdout, "get unknown section %s in portmap_white_lists\n", json_token_str(json, t));
goto out;
}
}
return i;
out:
free(pod->portmap_white_lists->internal_networks);
free(pod->portmap_white_lists->external_networks);
free(pod->portmap_white_lists);
pod->portmap_white_lists = NULL;
return -1;
}
int hyper_parse_pod(struct hyper_pod *pod, char *json, int length)
{
int i, n, next = -1;
@@ -1116,8 +1202,8 @@ realloc:
pod->policy = POLICY_ONFAILURE;
fprintf(stdout, "restartPolicy is %" PRIu8 "\n", pod->policy);
i++;
} else if (json_token_streq(json, t, "whiteCIDRs") && t->size == 1) {
next = hyper_parse_white_cidrs(pod, json, &toks[++i]);
} else if (json_token_streq(json, t, "portmappingWhiteLists") && t->size == 1) {
next = hyper_parse_portmapping_whitelist(pod, json, &toks[++i]);
if (next < 0)
goto out;
+99 -41
View File
@@ -66,7 +66,8 @@ int hyper_setup_iptables_rule(struct ipt_rule rule)
// initialize modules and iptables chains
int hyper_setup_portmapping(struct hyper_pod *pod)
{
if (pod->w_num == 0) {
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return 0;
}
@@ -152,7 +153,8 @@ int hyper_setup_portmapping(struct hyper_pod *pod)
void hyper_cleanup_portmapping(struct hyper_pod *pod)
{
if (pod->w_num == 0) {
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return;
}
@@ -242,11 +244,17 @@ void hyper_cleanup_portmapping(struct hyper_pod *pod)
return;
}
}
free(pod->portmap_white_lists->internal_networks);
free(pod->portmap_white_lists->external_networks);
free(pod->portmap_white_lists);
pod->portmap_white_lists = NULL;
}
int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod)
{
if (pod->w_num == 0) {
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return 0;
}
@@ -256,27 +264,54 @@ int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_po
int i = 0, j = 0;
char rule[128] = {0};
char *network = NULL;
for (i=0; i<c->ports_num; i++) {
sprintf(rule, "-p %s -m %s --dport %d -j REDIRECT --to-ports %d",
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].host_port,
c->ports[i].container_port);
struct ipt_rule rediect_rule = {
.table = "nat",
.op = "-I",
.chain = "hyperstart-PREROUTING",
.rule = rule,
};
if (hyper_setup_iptables_rule(rediect_rule)<0) {
fprintf(stderr, "setup rediect_rule '%s' failed\n", rule);
return -1;
// setup port mapping only if host_port is set
if (c->ports[i].host_port > 0) {
for (j=0; j<pod->portmap_white_lists->e_num; j++) {
network = pod->portmap_white_lists->external_networks[j];
// redirect host_port to container_port
sprintf(rule, "-s %s -p %s -m %s --dport %d -j REDIRECT --to-ports %d",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].host_port,
c->ports[i].container_port);
struct ipt_rule redirect_rule = {
.table = "nat",
.op = "-I",
.chain = "hyperstart-PREROUTING",
.rule = rule,
};
if (hyper_setup_iptables_rule(redirect_rule)<0) {
fprintf(stderr, "setup redirect_rule '%s' failed\n", rule);
return -1;
}
// open container_port to external network
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
struct ipt_rule accept_rule = {
.table = "filter",
.op = "-I",
.chain = "hyperstart-INPUT",
.rule = rule,
};
if (hyper_setup_iptables_rule(accept_rule)<0) {
fprintf(stderr, "setup accept_rule '%s' failed\n", rule);
return -1;
}
}
}
for (j=0; j<pod->w_num; j++) {
// only allow network request from white list
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
pod->white_cidrs[j],
pod->portmap_white_lists->internal_networks[j],
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
@@ -291,7 +326,6 @@ int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_po
return -1;
}
}
}
return 0;
@@ -299,7 +333,8 @@ int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_po
void hyper_cleanup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod)
{
if (pod->w_num == 0) {
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return;
}
@@ -307,29 +342,53 @@ void hyper_cleanup_container_portmapping(struct hyper_container *c, struct hyper
return;
}
int i = 0, j = 0;
char rule[128] = {0};
char *network = NULL;
for (i=0; i<c->ports_num; i++) {
sprintf(rule, "-p %s -m %s --dport %d -j REDIRECT --to-ports %d",
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].host_port,
c->ports[i].container_port);
struct ipt_rule rediect_rule = {
.table = "nat",
.op = "-D",
.chain = "hyperstart-PREROUTING",
.rule = rule,
};
if (hyper_setup_iptables_rule(rediect_rule)<0) {
fprintf(stderr, "setup rediect_rule '%s' failed\n", rule);
// clean up port mapping only if host_port is set
if (c->ports[i].host_port > 0) {
for (j=0; j<pod->portmap_white_lists->e_num; j++) {
network = pod->portmap_white_lists->external_networks[j];
// redirect host_port to container_port
sprintf(rule, "-s %s -p %s -m %s --dport %d -j REDIRECT --to-ports %d",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].host_port,
c->ports[i].container_port);
struct ipt_rule redirect_rule = {
.table = "nat",
.op = "-D",
.chain = "hyperstart-PREROUTING",
.rule = rule,
};
if (hyper_setup_iptables_rule(redirect_rule)<0) {
fprintf(stderr, "cleanup redirect '%s' failed\n", rule);
}
// open container_port to external network
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
struct ipt_rule accept_rule = {
.table = "filter",
.op = "-D",
.chain = "hyperstart-INPUT",
.rule = rule,
};
if (hyper_setup_iptables_rule(accept_rule)<0) {
fprintf(stderr, "cleanup accept_rule '%s' failed\n", rule);
}
}
}
for (j=0; j<pod->w_num; j++) {
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
pod->white_cidrs[j],
pod->portmap_white_lists->internal_networks[j],
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
@@ -340,9 +399,8 @@ void hyper_cleanup_container_portmapping(struct hyper_container *c, struct hyper
.rule = rule,
};
if (hyper_setup_iptables_rule(accept_rule)<0) {
fprintf(stderr, "setup accept_rule '%s' failed\n", rule);
fprintf(stderr, "cleanup accept_rule '%s' failed\n", rule);
}
}
}
}