1 #include "common.h"
2 
3 extern struct uwsgi_tuntap utt;
4 extern struct uwsgi_server uwsgi;
5 
uwsgi_tuntap_peer_rules_check(struct uwsgi_tuntap_router * uttr,struct uwsgi_tuntap_peer * uttp,char * pkt,size_t len,int direction)6 int uwsgi_tuntap_peer_rules_check(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp, char *pkt, size_t len, int direction) {
7 	if (uttp->rules_cnt == 0) return 0;
8 
9 	// sanity check
10         if (len < 20) return -1;
11         uint32_t *src_ip = (uint32_t *) &pkt[12];
12         uint32_t *dst_ip = (uint32_t *) &pkt[16];
13 
14         uint32_t src = ntohl(*src_ip);
15         uint32_t dst = ntohl(*dst_ip);
16 
17 #ifdef UWSGI_DEBUG
18 	uwsgi_log("%d %X %X\n",direction, src, dst);
19 #endif
20 
21 	int i;
22 	for(i=0;i<uttp->rules_cnt;i++) {
23 		struct uwsgi_tuntap_peer_rule *rule = &uttp->rules[i];
24 
25 #ifdef UWSGI_DEBUG
26 		uwsgi_log("cnt = %i/%d direction = %d action = %d %X %X\n", i, uttp->rules_cnt, rule->direction, rule->action, rule->src_mask, rule->dst_mask);
27 #endif
28 
29 
30 		if (rule->direction != direction) continue;
31 
32 		if (rule->src) {
33                         uint32_t src_masked = src & rule->src_mask;
34                         if (src_masked != rule->src) continue;
35                 }
36 
37                 if (rule->dst) {
38                         uint32_t dst_masked = dst & rule->dst_mask;
39                         if (dst_masked != rule->dst) continue;
40                 }
41 
42 
43 		if (rule->action == 0) return 0;
44 		if (rule->action == 1) return 1;
45 		if (rule->action == 2) {
46 			// if IN do not honour gateway/route
47 			if (!direction) return -1;
48 			if (uttr->gateway_fd > -1) {
49 				struct sockaddr_in sin;
50 				memset(&sin, 0, sizeof(struct sockaddr_in));
51 				sin.sin_family = AF_INET;
52 				sin.sin_port = rule->target_port;
53 				sin.sin_addr.s_addr = rule->target;
54 				if (sendto(uttr->gateway_fd, pkt, len, 0, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) {
55 					if (uwsgi_is_again()) {
56 						// suspend and retry
57 						struct pollfd pfd;
58 						memset(&pfd, 0, sizeof(struct pollfd));
59 						pfd.fd = uttr->gateway_fd;
60 						pfd.events = POLLOUT;
61 						int ret = poll(&pfd, 1, uwsgi.socket_timeout * 1000);
62 						if (ret > 0) {
63 							if (sendto(uttr->gateway_fd, pkt, len, 0, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) {
64 								uwsgi_tuntap_error(uttp,"uwsgi_tuntap_route_check()/sendto()");
65 							}
66 						}
67 						else {
68 							uwsgi_tuntap_error(uttp,"uwsgi_tuntap_route_check()/poll()");
69 						}
70 					}
71 					else {
72 						uwsgi_tuntap_error(uttp,"uwsgi_tuntap_route_check()/sendto()");
73 					}
74 				}
75 			}
76 			return 2;
77 		}
78 	}
79 	return 0;
80 }
81 
uwsgi_tuntap_firewall_check(struct uwsgi_tuntap_firewall_rule * direction,char * pkt,uint16_t len)82 int uwsgi_tuntap_firewall_check(struct uwsgi_tuntap_firewall_rule *direction, char *pkt, uint16_t len) {
83         // sanity check
84         if (len < 20) return -1;
85         uint32_t *src_ip = (uint32_t *) &pkt[12];
86         uint32_t *dst_ip = (uint32_t *) &pkt[16];
87 
88         uint32_t src = ntohl(*src_ip);
89         uint32_t dst = ntohl(*dst_ip);
90 
91         struct uwsgi_tuntap_firewall_rule *utfr = direction;
92         while(utfr) {
93                 if (utfr->src) {
94                         uint32_t src_masked = src & utfr->src_mask;
95                         if (src_masked != utfr->src) goto next;
96                 }
97 
98                 if (utfr->dst) {
99                         uint32_t dst_masked = dst & utfr->dst_mask;
100                         if (dst_masked != utfr->dst) goto next;
101                 }
102 
103                 return utfr->action;
104 next:
105                 utfr = utfr->next;
106         }
107 
108         return 0;
109 }
110 
uwsgi_tuntap_route_check(int fd,char * pkt,uint16_t len)111 int uwsgi_tuntap_route_check(int fd, char *pkt, uint16_t len) {
112         // sanity check
113         if (len < 20) return -1;
114         uint32_t *src_ip = (uint32_t *) &pkt[12];
115         uint32_t *dst_ip = (uint32_t *) &pkt[16];
116 
117         uint32_t src = ntohl(*src_ip);
118         uint32_t dst = ntohl(*dst_ip);
119 
120         struct uwsgi_tuntap_firewall_rule *utrr = utt.routes;
121         while(utrr) {
122                 if (utrr->src) {
123                         uint32_t src_masked = src & utrr->src_mask;
124                         if (src_masked != utrr->src) goto next;
125                 }
126 
127                 if (utrr->dst) {
128                         uint32_t dst_masked = dst & utrr->dst_mask;
129                         if (dst_masked != utrr->dst) goto next;
130                 }
131 
132 		if (sendto(fd, pkt, len, 0, (struct sockaddr *) &utrr->dest_addr, utrr->addrlen) < 0) {
133 			uwsgi_error("uwsgi_tuntap_route_check()/sendto()");
134 		}
135                 return 1;
136 next:
137                 utrr = utrr->next;
138         }
139 
140         return 0;
141 }
142 
143 
uwsgi_tuntap_firewall_add_rule(struct uwsgi_tuntap_firewall_rule ** direction,uint8_t action,uint32_t src,uint32_t src_mask,uint32_t dst,uint32_t dst_mask)144 static struct uwsgi_tuntap_firewall_rule *uwsgi_tuntap_firewall_add_rule(struct uwsgi_tuntap_firewall_rule **direction, uint8_t action, uint32_t src, uint32_t src_mask, uint32_t dst, uint32_t dst_mask) {
145 #ifdef UWSGI_DEBUG
146 	uwsgi_log("[tuntap-router] firewall action %d %x %x %x %x\n",action, src,src_mask,dst,dst_mask);
147 #endif
148 
149 	struct uwsgi_tuntap_firewall_rule *old_uttr = NULL, *uttr = *direction;
150 	while(uttr) {
151 		old_uttr = uttr;
152 		uttr = uttr->next;
153 	}
154 
155 	uttr = uwsgi_calloc(sizeof(struct uwsgi_tuntap_firewall_rule));
156 	uttr->action = action;
157 	uttr->src = src & src_mask;
158 	uttr->src_mask = src_mask;
159 	uttr->dst = dst & dst_mask;
160 	uttr->dst_mask = dst_mask;
161 
162 	if (old_uttr) {
163 		old_uttr->next = uttr;
164 	}
165 	else {
166 		*direction = uttr;
167 	}
168 
169 	return uttr;
170 }
171 
uwsgi_tuntap_opt_firewall(char * opt,char * value,void * direction)172 void uwsgi_tuntap_opt_firewall(char *opt, char *value, void *direction) {
173 
174 	char *space = strchr(value, ' ');
175 	if (!space) {
176 		if (!strcmp("deny", value)) {
177 			uwsgi_tuntap_firewall_add_rule((struct uwsgi_tuntap_firewall_rule **) direction, 1, 0, 0, 0, 0);
178 			return;
179 		}
180 		uwsgi_tuntap_firewall_add_rule((struct uwsgi_tuntap_firewall_rule **) direction, 0, 0, 0, 0, 0);
181 		return;
182 	}
183 
184 	*space = 0;
185 
186 	uint8_t action = 0;
187 	if (!strcmp(value, "deny")) action = 1;
188 
189 	char *space2 = strchr(space + 1, ' ');
190 	if (!space2) {
191 		uwsgi_log("invalid tuntap firewall rule syntax. must be <action> <src/mask> <dst/mask>");
192                 return;
193 	}
194 
195 	*space2 = 0;
196 
197 	uint32_t src = 0;
198 	uint32_t src_mask = 32;
199 	uint32_t dst = 0;
200 	uint32_t dst_mask = 32;
201 
202 	char *slash = strchr(space + 1 , '/');
203 	if (slash) {
204 		src_mask = atoi(slash+1);
205 		*slash = 0;
206 	}
207 
208 	if (inet_pton(AF_INET, space + 1, &src) != 1) {
209 		uwsgi_error("uwsgi_tuntap_opt_firewall()/inet_pton()");
210 		exit(1);
211 	}
212 
213 	if (slash) *slash = '/';
214 	*space = ' ';
215 
216 	slash = strchr(space2 + 1 , '/');
217         if (slash) {
218                 dst_mask = atoi(slash+1);
219                 *slash = 0;
220         }
221 
222         if (inet_pton(AF_INET, space2 + 1, &dst) != 1) {
223                 uwsgi_error("uwsgi_tuntap_opt_firewall()/inet_pton()");
224                 exit(1);
225         }
226 
227         if (slash) *slash = '/';
228         *space2 = ' ';
229 
230 	uwsgi_tuntap_firewall_add_rule((struct uwsgi_tuntap_firewall_rule **) direction, action, ntohl(src), (0xffffffff << (32-src_mask)), ntohl(dst), (0xffffffff << (32-dst_mask)));
231 }
232 
uwsgi_tuntap_opt_route(char * opt,char * value,void * table)233 void uwsgi_tuntap_opt_route(char *opt, char *value, void *table) {
234 
235         char *space = strchr(value, ' ');
236         if (!space) {
237 		uwsgi_log("invalid tuntap routing rule syntax, must be: <src/mask> <dst/mask> <gateway>\n");
238 		exit(1);
239 	}
240         *space = 0;
241 
242         char *space2 = strchr(space + 1, ' ');
243         if (!space2) {
244 		uwsgi_log("invalid tuntap routing rule syntax, must be: <src/mask> <dst/mask> <gateway>\n");
245 		exit(1);
246         }
247         *space2 = 0;
248 
249         uint32_t src = 0;
250         uint32_t src_mask = 32;
251         uint32_t dst = 0;
252         uint32_t dst_mask = 32;
253 
254         char *slash = strchr(value , '/');
255         if (slash) {
256                 src_mask = atoi(slash+1);
257                 *slash = 0;
258         }
259         if (inet_pton(AF_INET, value, &src) != 1) {
260                 uwsgi_error("uwsgi_tuntap_opt_route()/inet_pton()");
261                 exit(1);
262         }
263         if (slash) *slash = '/';
264 
265 	slash = strchr(space+1 , '/');
266         if (slash) {
267                 dst_mask = atoi(slash+1);
268                 *slash = 0;
269         }
270         if (inet_pton(AF_INET, space+1, &dst) != 1) {
271                 uwsgi_error("uwsgi_tuntap_opt_route()/inet_pton()");
272                 exit(1);
273         }
274         if (slash) *slash = '/';
275 
276 	*space = ' ';
277         *space2 = ' ';
278 
279         struct uwsgi_tuntap_firewall_rule * utfr = uwsgi_tuntap_firewall_add_rule((struct uwsgi_tuntap_firewall_rule **) table, 1, ntohl(src), (0xffffffff << (32-src_mask)), ntohl(dst), (0xffffffff << (32-dst_mask)));
280 	char *colon = strchr(space2+1, ':');
281 	if (!colon) {
282 		uwsgi_log("tuntap routing gateway must be a udp address in the form addr:port\n");
283 		exit(1);
284 	}
285 	utfr->dest_addr.sin_family = AF_INET;
286 	utfr->dest_addr.sin_port = htons(atoi(colon+1));
287 	*colon = 0;
288 	utfr->dest_addr.sin_addr.s_addr = inet_addr(space2+1);
289 	*colon = ':';
290 	utfr->addrlen = sizeof(struct sockaddr_in);
291 }
292 
uwsgi_tuntap_peer_send_rules(int fd,struct uwsgi_tuntap_peer * peer)293 void uwsgi_tuntap_peer_send_rules(int fd, struct uwsgi_tuntap_peer *peer) {
294 	struct uwsgi_string_list *usl = NULL;
295 	if (!utt.device_rules) return;
296 	struct uwsgi_buffer *ub = uwsgi_buffer_new(sizeof(struct uwsgi_tuntap_peer_rule) + 4);
297 	// leave space for the uwsgi header
298 	ub->pos = 4;
299 	uwsgi_foreach(usl, utt.device_rules) {
300 		size_t rlen;
301 		char **argv = uwsgi_split_quoted(usl->value, usl->len, " \t", &rlen);
302 		if (rlen < 4) {
303 			uwsgi_log("invalid tuntap device rule, must be <direction> <src/mask> <dst/mask> <action> [target]\n");
304 			exit(1);
305 		}
306 		struct uwsgi_tuntap_peer_rule utpr;
307 		memset(&utpr, 0, sizeof(struct uwsgi_tuntap_peer_rule));
308 		utpr.src_mask = 0xffffffff;
309 		utpr.dst_mask = 0xffffffff;
310 
311 		if (!strcmp(argv[0], "in")) {
312 			utpr.direction = 0;
313 		}
314 		else if (!strcmp(argv[0], "out")) {
315 			utpr.direction = 1;
316 		}
317 		else {
318 			uwsgi_log("invalid tuntap device rule direction, must be 'in' or 'out'\n");
319 			exit(1);
320 		}
321 
322 		char *slash = strchr(argv[1],'/');
323 		if (slash) {
324 			utpr.src_mask = (0xffffffff << ((atoi(slash+1))-32));
325 			*slash = 0;
326 		}
327 		if (inet_pton(AF_INET, argv[1], &utpr.src) != 1) {
328                 	uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/inet_pton()");
329                 	exit(1);
330 		}
331 		if (slash) *slash = '/';
332 		utpr.src = ntohl(utpr.src);
333 
334 		slash = strchr(argv[2],'/');
335                 if (slash) {
336 			utpr.dst_mask = (0xffffffff << ((atoi(slash+1))-32));
337                         *slash = 0;
338                 }
339                 if (inet_pton(AF_INET, argv[2], &utpr.dst) != 1) {
340                         uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/inet_pton()");
341                         exit(1);
342                 }
343                 if (slash) *slash = '/';
344 		utpr.dst = ntohl(utpr.dst);
345 
346 		if (!strcmp(argv[3], "deny")) {
347 			utpr.action = 1;
348 		}
349 		else if (!strcmp(argv[3], "allow")) {
350 			utpr.action = 0;
351 		}
352 		else if (!strcmp(argv[3], "route")) {
353 			utpr.action = 2;
354 		}
355 		else if (!strcmp(argv[3], "gateway")) {
356 			utpr.action = 2;
357 		}
358 		else {
359 			uwsgi_log("unsupported tuntap rule action: %s\n", argv[3]);
360 			exit(1);
361 		}
362 
363 		if (utpr.action == 2) {
364 			if (rlen < 4) {
365 				uwsgi_log("tuntap rule route/gateway requires a target\n");
366 				exit(1);
367 			}
368 			char *colon = strchr(argv[4], ':');
369 			if (!colon) {
370 				uwsgi_log("tuntap target must be in the form addr:port\n");
371 				exit(1);
372 			}
373 			*colon = 0;
374 			if (inet_pton(AF_INET, argv[4], &utpr.target) != 1) {
375                         	uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/inet_pton()");
376                         	exit(1);
377                 	}
378 			*colon = ':';
379 			utpr.target = utpr.target;
380 			utpr.target_port = htons(atoi(colon+1));
381 		}
382 
383 		if (uwsgi_buffer_append(ub, (char *) &utpr, sizeof(struct uwsgi_tuntap_peer_rule))) goto error;
384 		peer->rules_cnt++;
385         }
386 	// we still do not have an official modifier for the tuntap router
387 	if (uwsgi_buffer_set_uh(ub, 0, 1)) goto error;
388 	peer->rules = (struct uwsgi_tuntap_peer_rule *)ub->buf;
389 	ub->buf = NULL;
390 	size_t len = ub->pos;
391 	uwsgi_buffer_destroy(ub);
392 	if (write(fd,peer->rules, len) != (ssize_t)len) {
393 		uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/write()");
394 		exit(1);
395 	}
396 	return;
397 error:
398 	uwsgi_log("unable to create tuntap device rules packet\n");
399 	exit(1);
400 }
401