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