Merge branch 'tomato-ND-usbmod-vpn' into tomato-ND-USBmod
[tomato.git] / release / src / router / rc / firewall.c
blob35836603645171bf10c6015121526b9be426a27e
1 /*
3 Copyright 2003-2005, CyberTAN Inc. All Rights Reserved
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
6 the contents of this file may not be disclosed to third parties,
7 copied or duplicated in any form without the prior written
8 permission of CyberTAN Inc.
10 This software should be used as a reference only, and it not
11 intended for production use!
13 THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
14 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
15 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
16 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
21 Modified for Tomato Firmware
22 Portions, Copyright (C) 2006-2008 Jonathan Zarate
26 #include "rc.h"
28 #include <stdarg.h>
29 #include <arpa/inet.h>
30 #include <dirent.h>
32 char wanface[IFNAMSIZ];
33 char lanface[IFNAMSIZ];
34 char lan_cclass[sizeof("xxx.xxx.xxx.")];
35 char wanaddr[sizeof("xxx.xxx.xxx.xxx")];
36 static int web_lanport;
38 #ifdef DEBUG_IPTFILE
39 static int debug_only = 0;
40 #endif
42 static int gateway_mode;
43 static int remotemanage;
44 static int wanup;
46 const char *chain_in_drop;
47 const char *chain_in_accept;
48 const char *chain_out_drop;
49 const char *chain_out_accept;
50 const char *chain_out_reject;
52 const char ipt_fname[] = "/etc/iptables";
53 FILE *ipt_file;
57 struct {
58 } firewall_data;
61 // -----------------------------------------------------------------------------
64 void enable_ip_forward(void)
67 ip_forward - BOOLEAN
68 0 - disabled (default)
69 not 0 - enabled
71 Forward Packets between interfaces.
73 This variable is special, its change resets all configuration
74 parameters to their default state (RFC1122 for hosts, RFC1812
75 for routers)
77 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
81 // -----------------------------------------------------------------------------
84 static int ip2cclass(char *ipaddr, char *new, int count)
86 int ip[4];
88 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
89 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
94 static int dmz_dst(char *s)
96 struct in_addr ia;
97 char *p;
98 int n;
100 if (!nvram_match("dmz_enable", "1")) return 0;
102 p = nvram_safe_get("dmz_ipaddr");
103 if ((ia.s_addr = inet_addr(p)) == (in_addr_t)-1) {
104 if (((n = atoi(p)) <= 0) || (n >= 255)) return 0;
105 if (s) sprintf(s, "%s%d", lan_cclass, n);
106 return 1;
109 if (s) strcpy(s, inet_ntoa(ia));
110 return 1;
113 static void get_src(const char *nv, char *src)
115 char *p;
117 if (((p=nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
118 if (sscanf(p,"%*d.%*d.%*d.%*d-%*d.%*d.%*d.%*d") == 8)
119 sprintf(src, "-m iprange --src-range %s", p);
120 else
121 sprintf(src, "-s %s", p);
123 else {
124 *src = 0;
128 void ipt_write(const char *format, ...)
130 va_list args;
132 va_start(args, format);
133 vfprintf(ipt_file, format, args);
134 va_end(args);
138 // -----------------------------------------------------------------------------
141 int ipt_ipp2p(const char *v, char *opt)
143 int n = atoi(v);
145 if (n == 0) {
146 *opt = 0;
147 return 0;
150 strcpy(opt, "-m ipp2p ");
151 if ((n & 0xFFF) == 0xFFF) {
152 strcat(opt, "--ipp2p");
154 else {
155 // x12
156 if (n & 0x0001) strcat(opt, "--apple ");
157 if (n & 0x0002) strcat(opt, "--ares ");
158 if (n & 0x0004) strcat(opt, "--bit ");
159 if (n & 0x0008) strcat(opt, "--dc ");
160 if (n & 0x0010) strcat(opt, "--edk ");
161 if (n & 0x0020) strcat(opt, "--gnu ");
162 if (n & 0x0040) strcat(opt, "--kazaa ");
163 if (n & 0x0080) strcat(opt, "--mute ");
164 if (n & 0x0100) strcat(opt, "--soul ");
165 if (n & 0x0200) strcat(opt, "--waste ");
166 if (n & 0x0400) strcat(opt, "--winmx ");
167 if (n & 0x0800) strcat(opt, "--xdcc ");
170 modprobe("ipt_ipp2p");
171 return 1;
175 // -----------------------------------------------------------------------------
178 char **layer7_in;
180 // This L7 matches inbound traffic, caches the results, then the L7 outbound
181 // should read the cached result and set the appropriate marks -- zzz
182 void ipt_layer7_inbound(void)
184 int en;
185 char **p;
187 if (!layer7_in) return;
189 en = nvram_match("nf_l7in", "1");
190 if (en) {
191 ipt_write(
192 ":L7in - [0:0]\n"
193 "-A FORWARD -i %s -j L7in\n",
194 wanface);
197 p = layer7_in;
198 while (*p) {
199 if (en) ipt_write("-A L7in %s -j RETURN\n", *p);
200 free(*p);
201 ++p;
203 free(layer7_in);
204 layer7_in = NULL;
207 int ipt_layer7(const char *v, char *opt)
209 char s[128];
210 char *path;
212 *opt = 0;
213 if (*v == 0) return 0;
214 if (strlen(v) > 32) return -1;
216 path = "/etc/l7-extra";
217 sprintf(s, "%s/%s.pat", path, v);
218 if (!f_exists(s)) {
219 path = "/etc/l7-protocols";
220 sprintf(s, "%s/%s.pat", path, v);
221 if (!f_exists(s)) {
222 syslog(LOG_ERR, "L7 %s was not found", v);
223 return -1;
227 sprintf(opt, "-m layer7 --l7dir %s --l7proto %s", path, v);
229 if (nvram_match("nf_l7in", "1")) {
230 if (!layer7_in) layer7_in = calloc(51, sizeof(char *));
231 if (layer7_in) {
232 char **p;
234 p = layer7_in;
235 while (*p) {
236 if (strcmp(*p, opt) == 0) return 1;
237 ++p;
239 if (((p - layer7_in) / sizeof(char *)) < 50) *p = strdup(opt);
243 modprobe("ipt_layer7");
244 return 1;
249 // -----------------------------------------------------------------------------
250 // MANGLE
251 // -----------------------------------------------------------------------------
253 static void mangle_table(void)
255 int ttl;
256 char *p;
258 ipt_write(
259 "*mangle\n"
260 ":PREROUTING ACCEPT [0:0]\n"
261 ":OUTPUT ACCEPT [0:0]\n");
263 if (wanup) {
264 ipt_qos();
266 ttl = nvram_get_int("nf_ttl");
267 if (ttl != 0) {
268 modprobe("ipt_TTL");
269 if (ttl > 0) {
270 p = "in";
272 else {
273 ttl = -ttl;
274 p = "de";
276 ipt_write(
277 "-I PREROUTING -i %s -j TTL --ttl-%sc %d\n"
278 "-I POSTROUTING -o %s -j TTL --ttl-%sc %d\n",
279 wanface, p, ttl,
280 wanface, p, ttl);
284 ipt_write("COMMIT\n");
289 // -----------------------------------------------------------------------------
290 // NAT
291 // -----------------------------------------------------------------------------
293 in_addr_t _inet_addr(const char *cp)
295 struct in_addr a;
297 if (!inet_aton(cp, &a))
298 return INADDR_ANY;
299 else
300 return a.s_addr;
303 static void nat_table(void)
305 char lanaddr[32];
306 char lanmask[32];
307 char dst[64];
308 char src[64];
310 ipt_write("*nat\n"
311 ":PREROUTING ACCEPT [0:0]\n"
312 ":POSTROUTING ACCEPT [0:0]\n"
313 ":OUTPUT ACCEPT [0:0]\n");
314 if (gateway_mode) {
315 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
316 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
318 // Drop incoming packets which destination IP address is to our LAN side directly
319 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
320 wanface,
321 lanaddr, lanmask); // note: ipt will correct lanaddr
323 if (wanup) {
324 if (nvram_match("dns_intcpt", "1")) {
325 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
326 lanaddr, lanmask,
327 lanaddr, lanmask,
328 lanaddr);
331 // ICMP packets are always redirected to INPUT chains
332 ipt_write("-A PREROUTING -p icmp -d %s -j DNAT --to-destination %s\n", wanaddr, lanaddr);
334 get_src("rmgt_sip", src); // -s xxx or -m iprange --src-range xxx or ""
336 if (remotemanage) {
337 ipt_write("-A PREROUTING -p tcp -m tcp %s -d %s --dport %s -j DNAT --to-destination %s:%d\n",
338 src,
339 wanaddr, nvram_safe_get("http_wanport"),
340 lanaddr, web_lanport);
343 if (nvram_match("sshd_remote", "1")) {
344 ipt_write("-A PREROUTING %s -p tcp -m tcp -d %s --dport %s -j DNAT --to-destination %s:%s\n",
345 src,
346 wanaddr, nvram_safe_get("sshd_rport"),
347 lanaddr, nvram_safe_get("sshd_port"));
350 ipt_forward(IPT_TABLE_NAT);
351 ipt_triggered(IPT_TABLE_NAT);
354 if (nvram_match("upnp_enable", "1") || nvram_match("upnp_nat_pmp_enable", "1")) { //!!TB - miniupnpd
355 ipt_write(
356 ":upnp - [0:0]\n"
357 "-A PREROUTING -i %s -j upnp\n",
358 wanface);
361 if (wanup) {
362 if (dmz_dst(dst)) {
363 get_src("dmz_sip", src);
364 ipt_write("-A PREROUTING %s -d %s -j DNAT --to-destination %s\n", src, wanaddr, dst);
368 ////
370 /* Using SNAT instead of MASQUERADE can speed up routing since
371 * SNAT does not seek the external IP every time a chain is traversed.
372 * Recommended to use with kernel patch to drop SNAT'ed connections
373 * on wanface down or wanip change.
375 if (wanup && nvram_match("ne_snat", "1")) {
376 if (_inet_addr(wanaddr))
377 ipt_write("-A POSTROUTING -o %s ! -s %s -j SNAT --to-source %s\n",
378 wanface,
379 wanaddr, wanaddr);
381 /* SNAT physical WAN port connection */
382 char *wanip = nvram_safe_get("wan_ipaddr");
383 if (nvram_invmatch("wan_ifname", wanface) && _inet_addr(wanip))
384 ipt_write("-A POSTROUTING -o %s ! -s %s -j SNAT --to-source %s\n",
385 nvram_safe_get("wan_ifname"),
386 wanip, wanip);
388 else {
389 ipt_write("-A POSTROUTING -o %s -j MASQUERADE\n", wanface);
392 switch (nvram_get_int("nf_loopback")) {
393 case 1: // 1 = forwarded-only
394 case 2: // 2 = disable
395 break;
396 default: // 0 = all (same as block_loopback=0)
397 if (nvram_match("ne_snat", "1"))
398 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
399 lanface,
400 lanaddr, lanmask,
401 lanaddr, lanmask,
402 lanaddr);
403 else
404 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j MASQUERADE\n",
405 lanface,
406 lanaddr, lanmask,
407 lanaddr, lanmask);
408 break;
411 ipt_write("COMMIT\n");
414 // -----------------------------------------------------------------------------
415 // FILTER
416 // -----------------------------------------------------------------------------
418 static void filter_input(void)
420 char src[64];
422 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
423 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanaddr);
426 // filter known SPI state
427 ipt_write(
428 "-A INPUT -m state --state INVALID -j %s\n"
429 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
430 "-A INPUT -i %s -j ACCEPT\n"
431 "-A INPUT -i lo -j ACCEPT\n",
432 chain_in_drop,
433 lanface);
435 // ICMP request from WAN interface
436 if (nvram_match("block_wan", "0")) {
437 ipt_write("-A INPUT -p icmp -j ACCEPT\n");
440 get_src("rmgt_sip", src); // -s xxx or -m iprange --src-range xxx or ""
442 if (remotemanage) {
443 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %d -j %s\n",
444 src, nvram_safe_get("lan_ipaddr"), web_lanport, chain_in_accept);
447 if (nvram_match("sshd_remote", "1")) {
448 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %s -j %s\n",
449 src, nvram_safe_get("lan_ipaddr"), nvram_safe_get("sshd_port"), chain_in_accept);
452 #ifdef TCONFIG_FTP // !!TB - FTP Server
453 if (nvram_match("ftp_enable", "1")) {
454 ipt_write("-A INPUT -p tcp -m tcp --dport %s -j %s\n",
455 nvram_safe_get("ftp_port"), chain_in_accept);
457 #endif
459 // IGMP query from WAN interface
460 if (nvram_match("multicast_pass", "1")) {
461 ipt_write("-A INPUT -p igmp -j ACCEPT\n");
464 // Routing protocol, RIP, accept
465 if (nvram_invmatch("dr_wan_rx", "0")) {
466 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
469 // if logging
470 if (*chain_in_drop == 'l') {
471 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
474 // default policy: DROP
477 // clamp TCP MSS to PMTU of WAN interface
478 static void clampmss(void)
480 int rmtu = nvram_get_int("wan_run_mtu");
482 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu - 39);
483 if (rmtu < 576) {
484 ipt_write("--clamp-mss-to-pmtu\n");
486 else {
487 ipt_write("--set-mss %d\n", rmtu - 40);
491 static void filter_forward(void)
493 char dst[64];
494 char src[64];
496 ipt_write(
497 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
498 "-A FORWARD -m state --state INVALID -j DROP\n", // drop if INVALID state
499 lanface, lanface);
501 // clamp tcp mss to pmtu
502 clampmss();
504 if (wanup) {
505 ipt_restrictions();
506 ipt_layer7_inbound();
509 ipt_write(
510 ":wanin - [0:0]\n"
511 ":wanout - [0:0]\n"
512 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
513 "-A FORWARD -i %s -j wanin\n" // generic from wan
514 "-A FORWARD -o %s -j wanout\n" // generic to wan
515 "-A FORWARD -i %s -j %s\n", // from lan
516 wanface, wanface, lanface, chain_out_accept);
518 if (nvram_match("upnp_enable", "1") || nvram_match("upnp_nat_pmp_enable", "1")) { //!!TB - miniupnpd
519 ipt_write(
520 ":upnp - [0:0]\n"
521 "-A FORWARD -i %s -o ! %s -j upnp\n", //!!TB - miniupnpd
522 wanface, wanface); //!!TB - miniupnpd
525 if (wanup) {
526 if (nvram_match("multicast_pass", "1")) {
527 ipt_write("-A wanin -p udp -m udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
529 ipt_triggered(IPT_TABLE_FILTER);
530 ipt_forward(IPT_TABLE_FILTER);
532 if (dmz_dst(dst)) {
533 get_src("dmz_sip", src);
534 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface, src, dst, chain_in_accept);
539 // default policy: DROP
542 static void filter_table(void)
544 int n;
545 char limit[128];
547 ipt_write(
548 "*filter\n"
549 ":INPUT DROP [0:0]\n"
550 ":OUTPUT ACCEPT [0:0]\n"
553 n = nvram_get_int("log_limit");
554 if ((n >= 1) && (n <= 9999)) {
555 sprintf(limit, "-m limit --limit %d/m", n);
557 else {
558 limit[0] = 0;
561 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
562 ipt_write(
563 ":logdrop - [0:0]\n"
564 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
565 "-A logdrop -j DROP\n"
566 ":logreject - [0:0]\n"
567 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
568 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
569 limit, limit);
571 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
572 ipt_write(
573 ":logaccept - [0:0]\n"
574 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
575 "-A logaccept -j ACCEPT\n",
576 limit);
579 filter_input();
581 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
582 ipt_write(":FORWARD DROP [0:0]\n");
583 filter_forward();
585 else {
586 ipt_write(":FORWARD ACCEPT [0:0]\n");
587 clampmss();
589 ipt_write("COMMIT\n");
593 // -----------------------------------------------------------------------------
595 int start_firewall(void)
597 DIR *dir;
598 struct dirent *dirent;
599 char s[256];
600 char *c;
601 int n;
602 int wanproto;
604 simple_lock("firewall");
605 simple_lock("restrictions");
607 wanproto = get_wan_proto();
608 wanup = check_wanup();
612 block obviously spoofed IP addresses
614 rp_filter - BOOLEAN
615 1 - do source validation by reversed path, as specified in RFC1812
616 Recommended option for single homed hosts and stub network
617 routers. Could cause troubles for complicated (not loop free)
618 networks running a slow unreliable protocol (sort of RIP),
619 or using static routes.
620 0 - No source validation.
622 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
623 while ((dirent = readdir(dir)) != NULL) {
624 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
625 f_write_string(s, "1", 0, 0);
627 closedir(dir);
630 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
632 n = nvram_get_int("log_in");
633 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
634 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
636 n = nvram_get_int("log_out");
637 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
638 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
639 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
641 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
643 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
645 if ((wanproto == WP_PPTP) || (wanproto == WP_L2TP) || (wanproto == WP_PPPOE)) {
646 strcpy(wanface, "ppp+");
648 else {
649 strlcpy(wanface, nvram_safe_get("wan_ifname"), sizeof(wanface));
652 strlcpy(wanaddr, get_wanip(), sizeof(wanaddr));
654 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
655 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
656 strlcpy(lan_cclass, s, sizeof(lan_cclass));
658 gateway_mode = !nvram_match("wk_mode", "router");
659 if (gateway_mode) {
660 /* Remote management */
661 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
662 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
663 else remotemanage = 0;
665 if (nvram_match("remote_mgt_https", "1")) {
666 web_lanport = nvram_get_int("https_lanport");
667 if (web_lanport <= 0) web_lanport = 443;
669 else {
670 web_lanport = nvram_get_int("http_lanport");
671 if (web_lanport <= 0) web_lanport = 80;
676 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
677 syslog(LOG_CRIT, "Unable to create iptables restore file");
678 simple_unlock("firewall");
679 return 0;
682 mangle_table();
683 nat_table();
684 filter_table();
686 fclose(ipt_file);
687 ipt_file = NULL;
689 #ifdef DEBUG_IPTFILE
690 if (debug_only) {
691 simple_unlock("firewall");
692 return 0;
694 #endif
696 if (eval("iptables-restore", (char *)ipt_fname) == 0) {
697 // if (!nvram_match("debug_keepfiles", "1")) unlink(ipt_fname);
698 led(LED_DIAG, 0);
700 else {
701 sprintf(s, "%s.error", ipt_fname);
702 rename(ipt_fname, s);
703 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
704 led(LED_DIAG, 1);
708 -P INPUT DROP
709 -F INPUT
710 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
711 -A INPUT -i br0 -j ACCEPT
713 -P FORWARD DROP
714 -F FORWARD
715 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
716 -A FORWARD -i br0 -j ACCEPT
721 //!!TB - miniupnpd
722 if (nvram_match("upnp_enable", "1") || nvram_match("upnp_nat_pmp_enable", "1")) {
723 // flush all upnp rules
724 eval("iptables", "-t", "nat", "-F", "upnp");
725 eval("iptables", "-t", "filter", "-F", "upnp");
726 #ifdef TEST_MINIUPNP
727 // system("/tmp/upnptest post");
728 #else
729 // killall("upnp", SIGHUP);
730 #endif
733 simple_unlock("restrictions");
734 sched_restrictions();
735 enable_ip_forward();
737 led(LED_DMZ, dmz_dst(NULL));
739 modprobe_r("ipt_layer7");
740 modprobe_r("ipt_ipp2p");
741 modprobe_r("ipt_web");
742 modprobe_r("ipt_TTL");
744 #ifdef TCONFIG_OPENVPN
745 run_vpn_firewall_scripts();
746 #endif
747 run_nvscript("script_fire", NULL, 1);
749 simple_unlock("firewall");
750 return 0;
753 int stop_firewall(void)
755 led(LED_DMZ, 0);
756 return 0;
759 #ifdef DEBUG_IPTFILE
760 void create_test_iptfile(void)
762 debug_only = 1;
763 start_firewall();
764 debug_only = 0;
766 #endif