diff --git a/src/hyper.h b/src/hyper.h index 26d8685..3210f02 100644 --- a/src/hyper.h +++ b/src/hyper.h @@ -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; diff --git a/src/parse.c b/src/parse.c index 4430272..4c54ad1 100644 --- a/src/parse.c +++ b/src/parse.c @@ -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; diff --git a/src/portmapping.c b/src/portmapping.c index acce872..a9917e7 100644 --- a/src/portmapping.c +++ b/src/portmapping.c @@ -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; iports_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; jportmap_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; jw_num; j++) { + // only allow network request from white list + for (j=0; jportmap_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; iports_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; jportmap_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; jw_num; j++) { + for (j=0; jportmap_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); } } - } }