Comcast Fixes: DSCP and buffer overflow.
[tomato.git] / release / src / router / rc / firewall.c
blob34014147860ca346f243579c19addfc3e55e5c45
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-2009 Jonathan Zarate
26 #include "rc.h"
28 #include <stdarg.h>
29 #include <arpa/inet.h>
30 #include <dirent.h>
32 static int web_lanport;
33 wanface_list_t wanfaces;
34 char lanface[IFNAMSIZ + 1];
35 char lan1face[IFNAMSIZ + 1];
36 char lan2face[IFNAMSIZ + 1];
37 char lan3face[IFNAMSIZ + 1];
38 #ifdef TCONFIG_IPV6
39 char wan6face[IFNAMSIZ + 1];
40 #endif
41 char lan_cclass[sizeof("xxx.xxx.xxx.") + 1];
42 #ifdef LINUX26
43 static int can_enable_fastnat;
44 #endif
46 #ifdef DEBUG_IPTFILE
47 static int debug_only = 0;
48 #endif
50 static int gateway_mode;
51 static int remotemanage;
52 static int wanup;
54 const char *chain_in_drop;
55 const char *chain_in_accept;
56 const char *chain_out_drop;
57 const char *chain_out_accept;
58 const char *chain_out_reject;
60 const char chain_wan_prerouting[] = "WANPREROUTING";
61 const char ipt_fname[] = "/etc/iptables";
62 FILE *ipt_file;
64 #ifdef TCONFIG_IPV6
65 const char ip6t_fname[] = "/etc/ip6tables";
66 FILE *ip6t_file;
68 // RFC-4890, sec. 4.3.1
69 const int allowed_icmpv6[] = { 1, 2, 3, 4, 128, 129 };
70 #endif
72 static int is_sta(int idx, int unit, int subunit, void *param)
74 return (nvram_match(wl_nvname("mode", unit, subunit), "sta") && (nvram_match(wl_nvname("bss_enabled", unit, subunit), "1")));
78 struct {
79 } firewall_data;
82 // -----------------------------------------------------------------------------
84 #ifdef LINUX26
85 static const char *fastnat_run_dir = "/var/run/fastnat";
87 void allow_fastnat(const char *service, int allow)
89 char p[128];
91 snprintf(p, sizeof(p), "%s/%s", fastnat_run_dir, service);
92 if (allow) {
93 unlink(p);
95 else {
96 mkdir_if_none(fastnat_run_dir);
97 f_write_string(p, "", 0, 0);
101 static inline int fastnat_allowed(void)
103 DIR *dir;
104 struct dirent *dp;
105 int enabled;
107 enabled = !nvram_get_int("qos_enable") && !nvram_get_int("fastnat_disable");
109 if (enabled && (dir = opendir(fastnat_run_dir))) {
110 while ((dp = readdir(dir))) {
111 if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
112 continue;
113 enabled = 0;
114 break;
116 closedir(dir);
119 return (enabled);
122 void try_enabling_fastnat(void)
124 f_write_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_fastnat",
125 fastnat_allowed() ? "1" : "0", 0, 0);
127 #endif
129 void enable_ip_forward(void)
132 ip_forward - BOOLEAN
133 0 - disabled (default)
134 not 0 - enabled
136 Forward Packets between interfaces.
138 This variable is special, its change resets all configuration
139 parameters to their default state (RFC1122 for hosts, RFC1812
140 for routers)
142 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
146 #ifdef TCONFIG_IPV6
147 void enable_ip6_forward(void)
149 if (ipv6_enabled()) {
150 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "1", 0, 0);
151 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "1", 0, 0);
153 else {
154 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "0", 0, 0);
155 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "0", 0, 0);
158 #endif
161 // -----------------------------------------------------------------------------
164 static int ip2cclass(char *ipaddr, char *new, int count)
166 int ip[4];
168 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
169 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
174 static int dmz_dst(char *s)
176 struct in_addr ia;
177 char *p;
178 int n;
180 if (nvram_get_int("dmz_enable") <= 0) return 0;
182 p = nvram_safe_get("dmz_ipaddr");
183 if ((ia.s_addr = inet_addr(p)) == (in_addr_t)-1) {
184 if (((n = atoi(p)) <= 0) || (n >= 255)) return 0;
185 if (s) sprintf(s, "%s%d", lan_cclass, n);
186 return 1;
189 if (s) strcpy(s, inet_ntoa(ia));
190 return 1;
193 void ipt_log_unresolved(const char *addr, const char *addrtype, const char *categ, const char *name)
195 char *pre, *post;
197 pre = (name && *name) ? " for \"" : "";
198 post = (name && *name) ? "\"" : "";
200 syslog(LOG_WARNING, "firewall: "
201 "%s: not using %s%s%s%s (could not resolve as valid %s address)",
202 categ, addr, pre, (name) ? : "", post, (addrtype) ? : "IP");
205 int ipt_addr(char *addr, int maxlen, const char *s, const char *dir, int af,
206 int strict, const char *categ, const char *name)
208 char p[INET6_ADDRSTRLEN * 2];
209 int r = 0;
211 if ((s) && (*s) && (*dir))
213 if (sscanf(s, "%[0-9.]-%[0-9.]", p, p) == 2) {
214 snprintf(addr, maxlen, "-m iprange --%s-range %s", dir, s);
215 r = IPT_V4;
217 #ifdef TCONFIG_IPV6
218 else if (sscanf(s, "%[0-9A-Fa-f:]-%[0-9A-Fa-f:]", p, p) == 2) {
219 snprintf(addr, maxlen, "-m iprange --%s-range %s", dir, s);
220 r = IPT_V6;
222 #endif
223 else {
224 snprintf(addr, maxlen, "-%c %s", dir[0], s);
225 if (sscanf(s, "%[^/]/", p)) {
226 #ifdef TCONFIG_IPV6
227 r = host_addrtypes(p, strict ? af : (IPT_V4 | IPT_V6));
228 #else
229 r = host_addrtypes(p, IPT_V4);
230 #endif
234 else
236 *addr = 0;
237 r = (IPT_V4 | IPT_V6);
240 if ((r == 0 || (strict && ((r & af) != af))) && (categ && *categ)) {
241 ipt_log_unresolved(s, categ, name,
242 (af & IPT_V4 & ~r) ? "IPv4" : ((af & IPT_V6 & ~r) ? "IPv6" : NULL));
245 return (r & af);
248 #define ipt_source_strict(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 1, categ, name)
249 #define ipt_source(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 0, categ, name)
250 #define ip6t_source(s, src, categ, name) ipt_addr(src, 128, s, "src", IPT_V6, 0, categ, name)
253 static void get_src(const char *nv, char *src)
255 char *p;
257 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
258 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
260 else {
261 *src = 0;
266 void ipt_write(const char *format, ...)
268 va_list args;
270 va_start(args, format);
271 vfprintf(ipt_file, format, args);
272 va_end(args);
275 void ip6t_write(const char *format, ...)
277 #ifdef TCONFIG_IPV6
278 va_list args;
280 va_start(args, format);
281 vfprintf(ip6t_file, format, args);
282 va_end(args);
283 #endif
286 // -----------------------------------------------------------------------------
288 int ipt_dscp(const char *v, char *opt)
290 unsigned int n;
292 if (*v == 0) {
293 *opt = 0;
294 return 0;
297 n = strtoul(v, NULL, 0);
298 if (n > 63) n = 63;
299 sprintf(opt, " -m dscp --dscp 0x%02X", n);
301 #ifdef LINUX26
302 modprobe("xt_dscp");
303 #else
304 modprobe("ipt_dscp");
305 #endif
306 return 1;
309 // -----------------------------------------------------------------------------
312 int ipt_ipp2p(const char *v, char *opt)
314 int n = atoi(v);
316 if (n == 0) {
317 *opt = 0;
318 return 0;
321 strcpy(opt, "-m ipp2p ");
322 if ((n & 0xFFF) == 0xFFF) {
323 strcat(opt, "--ipp2p");
325 else {
326 // x12
327 if (n & 0x0001) strcat(opt, "--apple ");
328 if (n & 0x0002) strcat(opt, "--ares ");
329 if (n & 0x0004) strcat(opt, "--bit ");
330 if (n & 0x0008) strcat(opt, "--dc ");
331 if (n & 0x0010) strcat(opt, "--edk ");
332 if (n & 0x0020) strcat(opt, "--gnu ");
333 if (n & 0x0040) strcat(opt, "--kazaa ");
334 if (n & 0x0080) strcat(opt, "--mute ");
335 if (n & 0x0100) strcat(opt, "--soul ");
336 if (n & 0x0200) strcat(opt, "--waste ");
337 if (n & 0x0400) strcat(opt, "--winmx ");
338 if (n & 0x0800) strcat(opt, "--xdcc ");
339 #ifdef LINUX26
340 if (n & 0x1000) strcat(opt, "--pp ");
341 if (n & 0x2000) strcat(opt, "--xunlei ");
342 #endif
345 modprobe("ipt_ipp2p");
346 return 1;
350 // -----------------------------------------------------------------------------
353 char **layer7_in;
355 // This L7 matches inbound traffic, caches the results, then the L7 outbound
356 // should read the cached result and set the appropriate marks -- zzz
357 void ipt_layer7_inbound(void)
359 int en, i;
360 char **p;
362 if (!layer7_in) return;
364 en = nvram_match("nf_l7in", "1");
365 if (en) {
366 ipt_write(":L7in - [0:0]\n");
367 for (i = 0; i < wanfaces.count; ++i) {
368 if (*(wanfaces.iface[i].name)) {
369 ipt_write("-A FORWARD -i %s -j L7in\n",
370 wanfaces.iface[i].name);
375 p = layer7_in;
376 while (*p) {
377 if (en) {
378 ipt_write("-A L7in %s -j RETURN\n", *p);
379 #ifdef LINUX26
380 can_enable_fastnat = 0;
381 #endif
383 free(*p);
384 ++p;
386 free(layer7_in);
387 layer7_in = NULL;
390 int ipt_layer7(const char *v, char *opt)
392 char s[128];
393 char *path;
395 *opt = 0;
396 if (*v == 0) return 0;
397 if (strlen(v) > 32) return -1;
399 path = "/etc/l7-extra";
400 sprintf(s, "%s/%s.pat", path, v);
401 if (!f_exists(s)) {
402 path = "/etc/l7-protocols";
403 sprintf(s, "%s/%s.pat", path, v);
404 if (!f_exists(s)) {
405 syslog(LOG_ERR, "L7 %s was not found", v);
406 return -1;
410 sprintf(opt, "-m layer7 --l7dir %s --l7proto %s", path, v);
412 if (nvram_match("nf_l7in", "1")) {
413 if (!layer7_in) layer7_in = calloc(51, sizeof(char *));
414 if (layer7_in) {
415 char **p;
417 p = layer7_in;
418 while (*p) {
419 if (strcmp(*p, opt) == 0) return 1;
420 ++p;
422 if (((p - layer7_in) / sizeof(char *)) < 50) *p = strdup(opt);
426 #ifdef LINUX26
427 modprobe("xt_layer7");
428 #else
429 modprobe("ipt_layer7");
430 #endif
431 return 1;
434 // -----------------------------------------------------------------------------
436 static void ipt_account(void) {
437 struct in_addr ipaddr, netmask, network;
438 char lanN_ifname[] = "lanXX_ifname";
439 char lanN_ipaddr[] = "lanXX_ipaddr";
440 char lanN_netmask[] = "lanXX_netmask";
441 char lanN[] = "lanXX";
442 char netaddrnetmask[] = "255.255.255.255/255.255.255.255 ";
443 char br;
444 // If the IP Address changes, the below rule will cause things to choke, and blocking rules don't get applied
445 // As a workaround, flush the entire FORWARD chain
446 system("iptables -F FORWARD");
448 for(br=0 ; br<=3 ; br++) {
449 char bridge[2] = "0";
450 if (br!=0)
451 bridge[0]+=br;
452 else
453 strcpy(bridge, "");
455 sprintf(lanN_ifname, "lan%s_ifname", bridge);
457 if (strcmp(nvram_safe_get(lanN_ifname), "")!=0) {
459 sprintf(lanN_ipaddr, "lan%s_ipaddr", bridge);
460 sprintf(lanN_netmask, "lan%s_netmask", bridge);
461 sprintf(lanN, "lan%s", bridge);
463 inet_aton(nvram_safe_get(lanN_ipaddr), &ipaddr);
464 inet_aton(nvram_safe_get(lanN_netmask), &netmask);
466 // bitwise AND of ip and netmask gives the network
467 network.s_addr = ipaddr.s_addr & netmask.s_addr;
469 sprintf(netaddrnetmask, "%s/%s", inet_ntoa(network), nvram_safe_get(lanN_netmask));
471 //ipv4 only
472 ipt_write("-A FORWARD -m account --aaddr %s --aname %s\n", netaddrnetmask, lanN);
477 // -----------------------------------------------------------------------------
479 static void save_webmon(void)
481 eval("cp", "/proc/webmon_recent_domains", "/var/webmon/domain");
482 eval("cp", "/proc/webmon_recent_searches", "/var/webmon/search");
485 static void ipt_webmon()
487 int wmtype, clear, i;
488 char t[512];
489 char src[128];
490 char *p, *c;
491 int ok;
493 if (!nvram_get_int("log_wm")) return;
495 #ifdef LINUX26
496 can_enable_fastnat = 0;
497 #endif
498 wmtype = nvram_get_int("log_wmtype");
499 clear = nvram_get_int("log_wmclear");
501 ip46t_write(":monitor - [0:0]\n");
503 // include IPs
504 strlcpy(t, wmtype == 1 ? nvram_safe_get("log_wmip") : "", sizeof(t));
505 p = t;
506 do {
507 if ((c = strchr(p, ',')) != NULL) *c = 0;
509 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
510 #ifdef TCONFIG_IPV6
511 if (*wan6face && (ok & IPT_V6))
512 ip6t_write("-A FORWARD -o %s %s -j monitor\n", wan6face, src);
513 #endif
514 if (ok & IPT_V4) {
515 for (i = 0; i < wanfaces.count; ++i) {
516 if (*(wanfaces.iface[i].name)) {
517 ipt_write("-A FORWARD -o %s %s -j monitor\n",
518 wanfaces.iface[i].name, src);
524 if (!c) break;
525 p = c + 1;
526 } while (*p);
528 // exclude IPs
529 if (wmtype == 2) {
530 strlcpy(t, nvram_safe_get("log_wmip"), sizeof(t));
531 p = t;
532 do {
533 if ((c = strchr(p, ',')) != NULL) *c = 0;
534 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
535 if (*src)
536 ip46t_flagged_write(ok, "-A monitor %s -j RETURN\n", src);
538 if (!c) break;
539 p = c + 1;
540 } while (*p);
543 char webdomain[100];
544 char websearch[100];
546 if( nvram_match( "webmon_bkp", "1" ) ) {
547 xstart( "/usr/sbin/webmon_bkp", "add" ); // add jobs to cru
549 sprintf(webdomain, "--domain_load_file %s/webmon_recent_domains", nvram_safe_get("webmon_dir"));
550 sprintf(websearch, "--search_load_file %s/webmon_recent_searches", nvram_safe_get("webmon_dir"));
551 } else {
552 sprintf(webdomain, "--domain_load_file /var/webmon/domain");
553 sprintf(websearch, "--search_load_file /var/webmon/search");
556 ip46t_write(
557 "-A monitor -p tcp -m webmon "
558 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
559 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
560 (clear & 1) == 0 ? webdomain : "--clear_domain",
561 (clear & 2) == 0 ? websearch : "--clear_search");
563 if( nvram_match( "webmon_bkp", "1" ) )
564 xstart( "/usr/sbin/webmon_bkp", "hourly" ); // make a copy immediately
567 #ifdef LINUX26
568 modprobe("xt_webmon");
569 #else
570 modprobe("ipt_webmon");
571 #endif
576 // -----------------------------------------------------------------------------
577 // MANGLE
578 // -----------------------------------------------------------------------------
580 static void mangle_table(void)
582 int ttl;
583 char *p, *wanface;
585 ip46t_write(
586 "*mangle\n"
587 ":PREROUTING ACCEPT [0:0]\n"
588 ":OUTPUT ACCEPT [0:0]\n");
590 if (wanup) {
592 ipt_qos();
593 //1 for mangle
594 ipt_qoslimit(1);
596 p = nvram_safe_get("nf_ttl");
597 if (strncmp(p, "c:", 2) == 0) {
598 p += 2;
599 ttl = atoi(p);
600 p = (ttl >= 0 && ttl <= 255) ? "set" : NULL;
602 else if ((ttl = atoi(p)) != 0) {
603 if (ttl > 0) {
604 p = "inc";
606 else {
607 ttl = -ttl;
608 p = "dec";
610 if (ttl > 255) p = NULL;
612 else p = NULL;
614 if (p) {
615 #ifdef LINUX26
616 modprobe("xt_HL");
617 #else
618 modprobe("ipt_TTL");
619 #endif
620 // set TTL on primary WAN iface only
621 wanface = wanfaces.iface[0].name;
622 ipt_write(
623 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
624 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
625 wanface, p, ttl,
626 wanface, p, ttl);
627 #ifdef TCONFIG_IPV6
628 // FIXME: IPv6 HL should be configurable separately from TTL.
629 // disable it until GUI setting is implemented.
630 #if 0
631 ip6t_write(
632 "-I PREROUTING -i %s -j HL --hl-%s %d\n"
633 "-I POSTROUTING -o %s -j HL --hl-%s %d\n",
634 wan6face, p, ttl,
635 wan6face, p, ttl);
636 #endif
637 #endif
639 // Reset Incoming DSCP to 0x00
640 #ifdef LINUX26
641 modprobe("xt_DSCP");
642 #else
643 modprobe("ipt_DSCP");
644 #endif
645 ipt_write("-I PREROUTING -i %s -j DSCP --set-dscp 0\n", wanface);
648 ip46t_write("COMMIT\n");
651 // -----------------------------------------------------------------------------
652 // NAT
653 // -----------------------------------------------------------------------------
655 static void nat_table(void)
657 char lanaddr[32];
658 char lanmask[32];
659 char lan1addr[32];
660 char lan1mask[32];
661 char lan2addr[32];
662 char lan2mask[32];
663 char lan3addr[32];
664 char lan3mask[32];
665 char dst[64];
666 char src[64];
667 char t[512];
668 char *p, *c;
669 int i;
671 ipt_write("*nat\n"
672 ":PREROUTING ACCEPT [0:0]\n"
673 ":POSTROUTING ACCEPT [0:0]\n"
674 ":OUTPUT ACCEPT [0:0]\n"
675 ":%s - [0:0]\n",
676 chain_wan_prerouting);
678 //2 for nat
679 ipt_qoslimit(2);
681 if (gateway_mode) {
682 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
683 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
684 strlcpy(lan1addr, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr));
685 strlcpy(lan1mask, nvram_safe_get("lan1_netmask"), sizeof(lan1mask));
686 strlcpy(lan2addr, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr));
687 strlcpy(lan2mask, nvram_safe_get("lan2_netmask"), sizeof(lan2mask));
688 strlcpy(lan3addr, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr));
689 strlcpy(lan3mask, nvram_safe_get("lan3_netmask"), sizeof(lan3mask));
692 for (i = 0; i < wanfaces.count; ++i) {
693 if (*(wanfaces.iface[i].name)) {
694 // chain_wan_prerouting
695 if (wanup) {
696 ipt_write("-A PREROUTING -d %s -j %s\n",
697 wanfaces.iface[i].ip, chain_wan_prerouting);
700 // Drop incoming packets which destination IP address is to our LAN side directly
701 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
702 wanfaces.iface[i].name,
703 lanaddr, lanmask); // note: ipt will correct lanaddr
704 if(strcmp(lan1addr,"")!=0)
705 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
706 wanfaces.iface[i].name,
707 lan1addr, lan1mask);
708 if(strcmp(lan2addr,"")!=0)
709 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
710 wanfaces.iface[i].name,
711 lan2addr, lan2mask);
712 if(strcmp(lan3addr,"")!=0)
713 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
714 wanfaces.iface[i].name,
715 lan3addr, lan3mask);
719 if (wanup) {
720 if (nvram_match("dns_intcpt", "1")) {
721 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
722 lanaddr, lanmask,
723 lanaddr, lanmask,
724 lanaddr);
725 if(strcmp(lan1addr,"")!=0)
726 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
727 lan1addr, lan1mask,
728 lan1addr, lan1mask,
729 lan1addr);
730 if(strcmp(lan2addr,"")!=0)
731 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
732 lan2addr, lan2mask,
733 lan2addr, lan2mask,
734 lan2addr);
735 if(strcmp(lan3addr,"")!=0)
736 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
737 lan3addr, lan3mask,
738 lan3addr, lan3mask,
739 lan3addr);
742 // ICMP packets are always redirected to INPUT chains
743 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
746 //force remote access to router if DMZ is enabled - shibby
747 if( (nvram_match("dmz_enable", "1")) && (nvram_match("dmz_ra", "1")) ) {
748 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
749 p = t;
750 do {
751 if ((c = strchr(p, ',')) != NULL) *c = 0;
752 ipt_source(p, src, "ra", NULL);
754 if (remotemanage) {
755 ipt_write("-A %s -p tcp -m tcp %s --dport %s -j DNAT --to-destination %s:%d\n",
756 chain_wan_prerouting, src, nvram_safe_get("http_wanport"), lanaddr, web_lanport);
759 if (nvram_get_int("sshd_remote")) {
760 ipt_write("-A %s %s -p tcp -m tcp --dport %s -j DNAT --to-destination %s:%s\n",
761 chain_wan_prerouting, src, nvram_safe_get("sshd_rport"), lanaddr, nvram_safe_get("sshd_port"));
764 if (!c) break;
765 p = c + 1;
766 } while (*p);
770 ipt_forward(IPT_TABLE_NAT);
771 ipt_triggered(IPT_TABLE_NAT);
774 if (nvram_get_int("upnp_enable") & 3) {
775 ipt_write(":upnp - [0:0]\n");
777 for (i = 0; i < wanfaces.count; ++i) {
778 if (*(wanfaces.iface[i].name)) {
779 if (wanup) {
780 // ! for loopback (all) to work
781 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces.iface[i].ip);
783 else {
784 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces.iface[i].name);
790 #ifdef TCONFIG_TOR
791 //TOR
792 if (nvram_match("tor_enable", "1")) {
793 if (nvram_match("tor_iface", "br0")) {
794 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
795 nvram_safe_get("tor_iface"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("tor_transport") );
796 } else if (nvram_match("tor_iface", "br1")) {
797 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
798 nvram_safe_get("tor_iface"), nvram_safe_get("lan1_ipaddr"), nvram_safe_get("lan1_ipaddr"), nvram_safe_get("tor_transport") );
799 } else if (nvram_match("tor_iface", "br2")) {
800 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
801 nvram_safe_get("tor_iface"), nvram_safe_get("lan2_ipaddr"), nvram_safe_get("lan2_ipaddr"), nvram_safe_get("tor_transport") );
802 } else if (nvram_match("tor_iface", "br3")) {
803 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
804 nvram_safe_get("tor_iface"), nvram_safe_get("lan3_ipaddr"), nvram_safe_get("lan3_ipaddr"), nvram_safe_get("tor_transport") );
805 } else {
806 strlcpy(t, nvram_safe_get("tor_users"), sizeof(t));
807 p = t;
808 do {
809 if ((c = strchr(p, ',')) != NULL) *c = 0;
811 if (ipt_source_strict(p, src, "tor", NULL))
812 ipt_write("-A PREROUTING %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
813 src, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("tor_transport") );
815 if (!c) break;
816 p = c + 1;
817 } while (*p);
820 #endif
822 if (wanup) {
823 if (dmz_dst(dst)) {
824 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
825 p = t;
826 do {
827 if ((c = strchr(p, ',')) != NULL) *c = 0;
828 if (ipt_source_strict(p, src, "dmz", NULL))
829 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
830 if (!c) break;
831 p = c + 1;
832 } while (*p);
836 p = "";
837 #ifdef TCONFIG_IPV6
838 switch (get_ipv6_service()) {
839 case IPV6_6IN4:
840 // avoid NATing proto-41 packets when using 6in4 tunnel
841 p = "-p ! 41";
842 break;
844 #endif
846 for (i = 0; i < wanfaces.count; ++i) {
847 if (*(wanfaces.iface[i].name)) {
848 if ((!wanup) || (nvram_get_int("ne_snat") != 1))
849 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p, wanfaces.iface[i].name);
850 else
851 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p, wanfaces.iface[i].name, wanfaces.iface[i].ip);
855 char *modem_ipaddr;
856 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
857 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
858 && (!foreach_wif(1, NULL, is_sta)) )
859 ipt_write("-A POSTROUTING -o %s -d %s -j MASQUERADE\n", nvram_safe_get("wan_ifname"), modem_ipaddr);
861 switch (nvram_get_int("nf_loopback")) {
862 case 1: // 1 = forwarded-only
863 case 2: // 2 = disable
864 break;
865 default: // 0 = all (same as block_loopback=0)
866 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
867 lanface,
868 lanaddr, lanmask,
869 lanaddr, lanmask,
870 lanaddr);
871 if (strcmp(lan1face,"")!=0)
872 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
873 lan1face,
874 lan1addr, lan1mask,
875 lan1addr, lan1mask,
876 lan1addr);
877 if (strcmp(lan2face,"")!=0)
878 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
879 lan2face,
880 lan2addr, lan2mask,
881 lan2addr, lan2mask,
882 lan2addr);
883 if (strcmp(lan3face,"")!=0)
884 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
885 lan3face,
886 lan3addr, lan3mask,
887 lan3addr, lan3mask,
888 lan3addr);
889 break;
892 ipt_write("COMMIT\n");
895 // -----------------------------------------------------------------------------
896 // FILTER
897 // -----------------------------------------------------------------------------
899 static void filter_input(void)
901 char s[64];
902 char t[512];
903 char *en;
904 char *sec;
905 char *hit;
906 int n;
907 char *p, *c;
909 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
910 for (n = 0; n < wanfaces.count; ++n) {
911 if (*(wanfaces.iface[n].name)) {
912 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanfaces.iface[n].ip);
913 if (strcmp(lan1face,"")!=0)
914 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face, wanfaces.iface[n].ip);
915 if (strcmp(lan2face,"")!=0)
916 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face, wanfaces.iface[n].ip);
917 if (strcmp(lan3face,"")!=0)
918 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face, wanfaces.iface[n].ip);
923 ipt_write(
924 "-A INPUT -m state --state INVALID -j DROP\n"
925 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
927 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
928 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
930 ? what if the user uses the start button in GUI ?
931 if (nvram_get_int("telnetd_eas"))
932 if (nvram_get_int("sshd_eas"))
934 #ifdef LINUX26
935 modprobe("xt_recent");
936 #else
937 modprobe("ipt_recent");
938 #endif
940 ipt_write(
941 "-N shlimit\n"
942 "-A shlimit -m recent --set --name shlimit\n"
943 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
944 atoi(hit) + 1, sec, chain_in_drop);
946 if (n & 1) {
947 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
948 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
949 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
952 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
955 #ifdef TCONFIG_FTP
956 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
957 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
958 #ifdef LINUX26
959 modprobe("xt_recent");
960 #else
961 modprobe("ipt_recent");
962 #endif
964 ipt_write(
965 "-N ftplimit\n"
966 "-A ftplimit -m recent --set --name ftp\n"
967 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
968 atoi(hit) + 1, sec, chain_in_drop);
969 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
971 #endif
973 ipt_write(
974 "-A INPUT -i lo -j ACCEPT\n"
975 "-A INPUT -i %s -j ACCEPT\n",
976 lanface);
977 if (strcmp(lan1face,"")!=0)
978 ipt_write(
979 "-A INPUT -i %s -j ACCEPT\n",
980 lan1face);
981 if (strcmp(lan2face,"")!=0)
982 ipt_write(
983 "-A INPUT -i %s -j ACCEPT\n",
984 lan2face);
985 if (strcmp(lan3face,"")!=0)
986 ipt_write(
987 "-A INPUT -i %s -j ACCEPT\n",
988 lan3face);
990 #ifdef TCONFIG_IPV6
991 n = get_ipv6_service();
992 switch (n) {
993 case IPV6_ANYCAST_6TO4:
994 case IPV6_6IN4:
995 // Accept ICMP requests from the remote tunnel endpoint
996 if (n == IPV6_ANYCAST_6TO4)
997 sprintf(s, "192.88.99.%d", nvram_get_int("ipv6_relay"));
998 else
999 strlcpy(s, nvram_safe_get("ipv6_tun_v4end"), sizeof(s));
1000 if (*s && strcmp(s, "0.0.0.0") != 0)
1001 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s, chain_in_accept);
1002 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept);
1003 break;
1005 #endif
1007 // ICMP request from WAN interface
1008 if (nvram_match("block_wan", "0")) {
1009 if (nvram_match("block_wan_limit", "0")) {
1010 // allow ICMP packets to be received
1011 ipt_write("-A INPUT -p icmp -j %s\n", chain_in_accept);
1012 // allow udp traceroute packets
1013 ipt_write("-A INPUT -p udp --dport 33434:33534 -j %s\n", chain_in_accept);
1014 } else {
1015 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
1016 ipt_write("-A INPUT -p icmp -m limit --limit %d/second -j %s\n", nvram_get_int("block_wan_limit_icmp"), chain_in_accept);
1017 // allow udp traceroute packets, but restrict the flow to avoid ping flood attacks
1018 ipt_write("-A INPUT -p udp --dport 33434:33534 -m limit --limit %d/second -j %s\n", nvram_get_int("block_wan_limit_tr"), chain_in_accept);
1022 /* Accept incoming packets from broken dhcp servers, which are sending replies
1023 * from addresses other than used for query. This could lead to a lower level
1024 * of security, so allow to disable it via nvram variable.
1026 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
1027 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
1030 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1031 p = t;
1032 do {
1033 if ((c = strchr(p, ',')) != NULL) *c = 0;
1035 if (ipt_source(p, s, "remote management", NULL)) {
1037 if (remotemanage) {
1038 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1039 s, nvram_safe_get("http_wanport"), chain_in_accept);
1042 if (nvram_get_int("sshd_remote")) {
1043 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1044 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1048 if (!c) break;
1049 p = c + 1;
1050 } while (*p);
1052 #ifdef TCONFIG_NGINX //Tomato RAF - Web Server
1053 if (nvram_match("nginx_enable", "1"))
1054 ipt_write("-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "nginx_port" ));
1055 #endif
1057 #ifdef TCONFIG_FTP // !!TB - FTP Server
1058 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1059 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1060 p = t;
1061 do {
1062 if ((c = strchr(p, ',')) != NULL) *c = 0;
1063 if (ipt_source(p, s, "ftp", "remote access")) {
1064 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1065 s, nvram_safe_get("ftp_port"), chain_in_accept);
1067 if (!c) break;
1068 p = c + 1;
1069 } while (*p);
1071 #endif
1073 #ifdef TCONFIG_SNMP
1074 if( nvram_match( "snmp_enable", "1" ) && nvram_match("snmp_remote", "1"))
1076 strlcpy(t, nvram_safe_get("snmp_remote_sip"), sizeof(t));
1077 p = t;
1078 do {
1079 if ((c = strchr(p, ',')) != NULL) *c = 0;
1081 if (ipt_source(p, s, "snmp", "remote")) {
1082 ipt_write("-A INPUT -p udp %s --dport %s -j %s\n",
1083 s, nvram_safe_get("snmp_port"), chain_in_accept);
1086 if (!c) break;
1087 p = c + 1;
1088 } while (*p);
1090 #endif
1092 // IGMP query from WAN interface
1093 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1094 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
1095 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
1098 // Routing protocol, RIP, accept
1099 if (nvram_invmatch("dr_wan_rx", "0")) {
1100 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
1103 //BT Client ports from WAN interface
1104 if (nvram_match("bt_enable", "1")) {
1105 ipt_write( "-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "bt_port" ) );
1106 if (nvram_match( "bt_rpc_wan", "1") )
1108 ipt_write( "-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "bt_port_gui" ) );
1112 // if logging
1113 if (*chain_in_drop == 'l') {
1114 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
1117 // default policy: DROP
1120 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
1121 static void clampmss(void)
1123 #if 1
1124 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1125 #else
1126 int rmtu = nvram_get_int("wan_run_mtu");
1127 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu - 39);
1128 if (rmtu < 576) {
1129 ipt_write("--clamp-mss-to-pmtu\n");
1131 else {
1132 ipt_write("--set-mss %d\n", rmtu - 40);
1134 #endif
1137 static void filter_forward(void)
1139 char dst[64];
1140 char src[64];
1141 char t[512];
1142 char *p, *c;
1143 int i;
1145 #ifdef TCONFIG_IPV6
1146 ip6t_write(
1147 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
1148 #endif
1150 if (nvram_match("cstats_enable", "1")) {
1151 ipt_account();
1154 ip46t_write(
1155 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
1156 lanface, lanface);
1157 if (strcmp(lan1face,"")!=0)
1158 ip46t_write(
1159 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1160 lan1face, lan1face);
1161 if (strcmp(lan2face,"")!=0)
1162 ip46t_write(
1163 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1164 lan2face, lan2face);
1165 if (strcmp(lan3face,"")!=0)
1166 ip46t_write(
1167 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1168 lan3face, lan3face);
1170 char lanAccess[17] = "0000000000000000";
1172 const char *d, *sbr, *saddr, *dbr, *daddr, *desc;
1173 char *nv, *nvp, *b;
1174 int n;
1175 nvp = nv = strdup(nvram_safe_get("lan_access"));
1176 if (nv) {
1177 while ((b = strsep(&nvp, ">")) != NULL) {
1179 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
1181 1 = enabled
1182 0 = src bridge
1183 1.2.3.4 = src addr
1184 1 = dst bridge
1185 5.6.7.8 = dst addr
1186 desc = desc
1188 n = vstrsep(b, "<", &d, &sbr, &saddr, &dbr, &daddr, &desc);
1189 if (*d != '1')
1190 continue;
1191 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4|IPT_V6, 0, "LAN access", desc))
1192 continue;
1193 if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V4|IPT_V6, 0, "LAN access", desc))
1194 continue;
1196 //ipv4 only
1197 ipt_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
1198 "br",
1199 sbr,
1200 "br",
1201 dbr,
1202 src,
1203 dst);
1205 if ((strcmp(src,"")==0) && (strcmp(dst,"")==0))
1206 lanAccess[((*sbr-48)+(*dbr-48)*4)] = '1';
1210 free(nv);
1212 ip46t_write(
1213 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
1215 // clamp tcp mss to pmtu
1216 clampmss();
1218 if (wanup) {
1219 ipt_restrictions();
1221 ipt_layer7_inbound();
1224 ipt_webmon();
1226 ip46t_write(
1227 ":wanin - [0:0]\n"
1228 ":wanout - [0:0]\n"
1229 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1231 char lanN_ifname[] = "lanXX_ifname";
1232 char br;
1233 for(br=0 ; br<=3 ; br++) {
1234 char bridge[2] = "0";
1235 if (br!=0)
1236 bridge[0]+=br;
1237 else
1238 strcpy(bridge, "");
1240 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1241 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1242 char lanN_ifname2[] = "lanXX_ifname";
1243 char br2;
1244 for(br2=0 ; br2<=3 ; br2++) {
1245 if (br==br2) continue;
1247 if (lanAccess[((br)+(br2)*4)] == '1') continue;
1249 char bridge2[2] = "0";
1250 if (br2!=0)
1251 bridge2[0]+=br2;
1252 else
1253 strcpy(bridge2, "");
1255 sprintf(lanN_ifname2, "lan%s_ifname", bridge2);
1256 if (strncmp(nvram_safe_get(lanN_ifname2), "br", 2) == 0) {
1257 ipt_write("-A FORWARD -i %s -o %s -j DROP\n",
1258 nvram_safe_get(lanN_ifname),
1259 nvram_safe_get(lanN_ifname2));
1262 // ip46t_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1266 #ifdef TCONFIG_PPTPD
1267 //Add for pptp server
1268 if (nvram_match("pptpd_enable", "1")) {
1269 ipt_write("-A INPUT -p tcp --dport 1723 -j ACCEPT\n");
1270 ipt_write("-A INPUT -p 47 -j ACCEPT\n");
1272 #endif
1274 #ifdef TCONFIG_IPV6
1275 // Filter out invalid WAN->WAN connections
1276 if (*wan6face)
1277 // ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face, lanface, chain_in_drop); //shibby - we cant drop connections from WAN to LAN1-3
1278 ip6t_write("-A FORWARD -o %s -i %s -j %s\n", wan6face, wan6face, chain_in_drop); //shibby - drop connection from WAN -> WAN only
1280 #ifdef LINUX26
1281 modprobe("xt_length");
1282 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1283 #endif
1285 // ICMPv6 rules
1286 for (i = 0; i < sizeof(allowed_icmpv6)/sizeof(int); ++i) {
1287 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[i], chain_in_accept);
1290 //IPv6
1291 if (*wan6face) {
1292 ip6t_write(
1293 "-A FORWARD -i %s -j wanin\n" // generic from wan
1294 "-A FORWARD -o %s -j wanout\n", // generic to wan
1295 wan6face, wan6face);
1297 #endif
1299 //IPv4
1300 for (i = 0; i < wanfaces.count; ++i) {
1301 if (*(wanfaces.iface[i].name)) {
1302 ipt_write(
1303 "-A FORWARD -i %s -j wanin\n" // generic from wan
1304 "-A FORWARD -o %s -j wanout\n", // generic to wan
1305 wanfaces.iface[i].name, wanfaces.iface[i].name);
1309 for(br=0 ; br<=3 ; br++) {
1310 char bridge[2] = "0";
1311 if (br!=0)
1312 bridge[0]+=br;
1313 else
1314 strcpy(bridge, "");
1316 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1317 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1318 ip46t_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1322 #ifdef TCONFIG_IPV6
1323 //IPv6 forward LAN->WAN accept
1324 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wan6face, chain_out_accept);
1326 if (strcmp(lan1face,"")!=0)
1327 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wan6face, chain_out_accept);
1328 if (strcmp(lan2face,"")!=0)
1329 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wan6face, chain_out_accept);
1330 if (strcmp(lan3face,"")!=0)
1331 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wan6face, chain_out_accept);
1332 #endif
1334 // IPv4 only
1335 if (nvram_get_int("upnp_enable") & 3) {
1336 ipt_write(":upnp - [0:0]\n");
1337 for (i = 0; i < wanfaces.count; ++i) {
1338 if (*(wanfaces.iface[i].name)) {
1339 ipt_write("-A FORWARD -i %s -j upnp\n",
1340 wanfaces.iface[i].name);
1345 if (wanup) {
1346 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1347 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
1349 ipt_triggered(IPT_TABLE_FILTER);
1350 ipt_forward(IPT_TABLE_FILTER);
1351 #ifdef TCONFIG_IPV6
1352 ip6t_forward();
1353 #endif
1355 if (dmz_dst(dst)) {
1356 char dmz_ifname[IFNAMSIZ+1];
1357 strlcpy(dmz_ifname, nvram_safe_get("dmz_ifname"), sizeof(dmz_ifname));
1358 if(strcmp(dmz_ifname, "") == 0)
1359 strlcpy(dmz_ifname, lanface, sizeof(lanface));
1360 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
1361 p = t;
1362 do {
1363 if ((c = strchr(p, ',')) != NULL) *c = 0;
1364 if (ipt_source(p, src, "dmz", NULL))
1365 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", dmz_ifname, src, dst, chain_in_accept);
1366 if (!c) break;
1367 p = c + 1;
1368 } while (*p);
1372 // default policy: DROP
1375 static void filter_log(void)
1377 int n;
1378 char limit[128];
1380 n = nvram_get_int("log_limit");
1381 if ((n >= 1) && (n <= 9999)) {
1382 sprintf(limit, "-m limit --limit %d/m", n);
1384 else {
1385 limit[0] = 0;
1388 #ifdef TCONFIG_IPV6
1389 modprobe("ip6t_LOG");
1390 #endif
1391 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
1392 ip46t_write(
1393 ":logdrop - [0:0]\n"
1394 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1395 #ifdef LINUX26
1396 " --log-macdecode"
1397 #endif
1398 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1399 "-A logdrop -j DROP\n"
1400 ":logreject - [0:0]\n"
1401 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1402 #ifdef LINUX26
1403 " --log-macdecode"
1404 #endif
1405 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1406 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1407 limit, limit);
1409 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
1410 ip46t_write(
1411 ":logaccept - [0:0]\n"
1412 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1413 #ifdef LINUX26
1414 " --log-macdecode"
1415 #endif
1416 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1417 "-A logaccept -j ACCEPT\n",
1418 limit);
1422 #ifdef TCONFIG_IPV6
1423 static void filter6_input(void)
1425 char s[128];
1426 char t[512];
1427 char *en;
1428 char *sec;
1429 char *hit;
1430 int n;
1431 char *p, *c;
1433 // RFC-4890, sec. 4.4.1
1434 const int allowed_local_icmpv6[] =
1435 { 130, 131, 132, 133, 134, 135, 136,
1436 141, 142, 143,
1437 148, 149, 151, 152, 153 };
1439 ip6t_write(
1440 "-A INPUT -m rt --rt-type 0 -j %s\n"
1441 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1442 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1443 chain_in_drop);
1445 #ifdef LINUX26
1446 modprobe("xt_length");
1447 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1448 #endif
1450 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
1451 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
1452 #ifdef LINUX26
1453 modprobe("xt_recent");
1454 #else
1455 modprobe("ipt_recent");
1456 #endif
1458 ip6t_write(
1459 "-N shlimit\n"
1460 "-A shlimit -m recent --set --name shlimit\n"
1461 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1462 atoi(hit) + 1, sec, chain_in_drop);
1464 if (n & 1) {
1465 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
1466 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1467 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1470 if (n & 2) ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("telnetd_port"));
1473 #ifdef TCONFIG_FTP
1474 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
1475 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
1476 #ifdef LINUX26
1477 modprobe("xt_recent");
1478 #else
1479 modprobe("ipt_recent");
1480 #endif
1482 ip6t_write(
1483 "-N ftplimit\n"
1484 "-A ftplimit -m recent --set --name ftp\n"
1485 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1486 atoi(hit) + 1, sec, chain_in_drop);
1487 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1489 #endif // TCONFIG_FTP
1491 ip6t_write(
1492 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1493 "-A INPUT -i lo -j ACCEPT\n",
1494 lanface );
1496 switch (get_ipv6_service()) {
1497 case IPV6_ANYCAST_6TO4:
1498 case IPV6_NATIVE_DHCP:
1499 // allow responses from the dhcpv6 server
1500 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept);
1501 break;
1504 // ICMPv6 rules
1505 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
1506 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
1508 for (n = 0; n < sizeof(allowed_local_icmpv6)/sizeof(int); n++) {
1509 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6[n], chain_in_accept);
1512 // Remote Managment
1513 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1514 p = t;
1515 do {
1516 if ((c = strchr(p, ',')) != NULL) *c = 0;
1518 if (ip6t_source(p, s, "remote management", NULL)) {
1520 if (remotemanage) {
1521 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1522 s, nvram_safe_get("http_wanport"), chain_in_accept);
1525 if (nvram_get_int("sshd_remote")) {
1526 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1527 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1531 if (!c) break;
1532 p = c + 1;
1533 } while (*p);
1535 #ifdef TCONFIG_FTP
1536 // FTP server
1537 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1538 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1539 p = t;
1540 do {
1541 if ((c = strchr(p, ',')) != NULL) *c = 0;
1542 if (ip6t_source(p, s, "ftp", "remote access")) {
1543 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1544 s, nvram_safe_get("ftp_port"), chain_in_accept);
1546 if (!c) break;
1547 p = c + 1;
1548 } while (*p);
1550 #endif
1552 // if logging
1553 if (*chain_in_drop == 'l') {
1554 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
1557 // default policy: DROP
1560 #endif
1562 static void filter_table(void)
1564 ip46t_write(
1565 "*filter\n"
1566 ":INPUT DROP [0:0]\n"
1567 ":OUTPUT ACCEPT [0:0]\n"
1570 filter_log();
1572 filter_input();
1573 #ifdef TCONFIG_IPV6
1574 filter6_input();
1575 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop);
1576 #endif
1578 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
1579 ip46t_write(":FORWARD DROP [0:0]\n");
1580 filter_forward();
1582 else {
1583 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1584 clampmss();
1586 ip46t_write("COMMIT\n");
1589 // -----------------------------------------------------------------------------
1591 int start_firewall(void)
1593 DIR *dir;
1594 struct dirent *dirent;
1595 char s[256];
1596 char *c, *wanface;
1597 int n;
1598 int wanproto;
1599 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
1600 #ifdef TCONFIG_IPV6
1601 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
1602 #endif
1604 simple_lock("firewall");
1605 simple_lock("restrictions");
1607 wanup = check_wanup();
1609 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1611 /* NAT performance tweaks
1612 * These values can be overriden later if needed via firewall script
1614 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1615 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1616 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1617 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1618 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1619 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1620 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1621 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1622 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1623 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1624 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1625 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1627 /* DoS-related tweaks */
1628 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1629 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1630 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1632 wanproto = get_wan_proto();
1633 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto == WP_DISABLED || wanproto == WP_STATIC) ? "0" : "1", 0, 0);
1635 #ifdef TCONFIG_EMF
1636 /* Force IGMPv2 due EMF limitations */
1637 if (nvram_get_int("emf_enable")) {
1638 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1639 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1641 #endif
1643 n = nvram_get_int("log_in");
1644 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1645 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1647 n = nvram_get_int("log_out");
1648 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1649 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1650 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1652 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1654 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1655 strlcpy(lan1face, nvram_safe_get("lan1_ifname"), IFNAMSIZ);
1656 strlcpy(lan2face, nvram_safe_get("lan2_ifname"), IFNAMSIZ);
1657 strlcpy(lan3face, nvram_safe_get("lan3_ifname"), IFNAMSIZ);
1659 memcpy(&wanfaces, get_wanfaces(), sizeof(wanfaces));
1660 wanface = wanfaces.iface[0].name;
1661 #ifdef TCONFIG_IPV6
1662 strlcpy(wan6face, get_wan6face(), sizeof(wan6face));
1663 #endif
1665 #ifdef LINUX26
1666 can_enable_fastnat = 1;
1667 #endif
1669 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1670 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1671 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1673 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1674 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1675 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1677 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1678 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1679 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1681 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1682 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1683 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1687 block obviously spoofed IP addresses
1689 rp_filter - BOOLEAN
1690 1 - do source validation by reversed path, as specified in RFC1812
1691 Recommended option for single homed hosts and stub network
1692 routers. Could cause troubles for complicated (not loop free)
1693 networks running a slow unreliable protocol (sort of RIP),
1694 or using static routes.
1695 0 - No source validation.
1697 c = nvram_get("wan_ifname");
1698 /* mcast needs rp filter to be turned off only for non default iface */
1699 if (!(nvram_match("multicast_pass", "1")) || !(nvram_match("udpxy_enable", "1")) || strcmp(wanface, c) == 0) c = NULL;
1701 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1702 while ((dirent = readdir(dir)) != NULL) {
1703 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
1704 f_write_string(s, (c && strcmp(dirent->d_name, c) == 0) ? "0" : "1", 0, 0);
1706 closedir(dir);
1709 remotemanage = 0;
1710 gateway_mode = !nvram_match("wk_mode", "router");
1711 if (gateway_mode) {
1712 /* Remote management */
1713 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1714 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1716 if (nvram_match("remote_mgt_https", "1")) {
1717 web_lanport = nvram_get_int("https_lanport");
1718 if (web_lanport <= 0) web_lanport = 443;
1719 } else {
1720 web_lanport = nvram_get_int("http_lanport");
1721 if (web_lanport <= 0) web_lanport = 80;
1725 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1726 notice_set("iptables", "Unable to create iptables restore file");
1727 simple_unlock("firewall");
1728 return 0;
1731 #ifdef TCONFIG_IPV6
1732 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1733 notice_set("ip6tables", "Unable to create ip6tables restore file");
1734 simple_unlock("firewall");
1735 return 0;
1737 modprobe("nf_conntrack_ipv6");
1738 modprobe("ip6t_REJECT");
1739 #endif
1741 //shibby
1742 //if (nvram_match("imq_enable", "1")) {
1743 // char numdevs[10];
1744 // sprintf(numdevs, "numdevs=%d", nvram_get_int("imq_numdevs"));
1745 // modprobe("imq", numdevs );
1747 modprobe("imq");
1748 #ifdef LINUX26
1749 modprobe("xt_IMQ");
1750 #else
1751 modprobe("ipt_IMQ");
1752 #endif
1753 // }
1756 mangle_table();
1757 nat_table();
1758 filter_table();
1760 fclose(ipt_file);
1761 ipt_file = NULL;
1763 #ifdef TCONFIG_IPV6
1764 fclose(ip6t_file);
1765 ip6t_file = NULL;
1766 #endif
1768 #ifdef DEBUG_IPTFILE
1769 if (debug_only) {
1770 simple_unlock("firewall");
1771 simple_unlock("restrictions");
1772 return 0;
1774 #endif
1776 save_webmon();
1778 if (nvram_get_int("upnp_enable") & 3) {
1779 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1780 if (killall("miniupnpd", SIGUSR2) == 0) {
1781 f_wait_notexists("/etc/upnp/save", 5);
1785 notice_set("iptables", "");
1786 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1787 led(LED_DIAG, 0);
1788 notice_set("iptables", "");
1790 else {
1791 sprintf(s, "%s.error", ipt_fname);
1792 rename(ipt_fname, s);
1793 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1794 led(LED_DIAG, 1);
1798 -P INPUT DROP
1799 -F INPUT
1800 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1801 -A INPUT -i br0 -j ACCEPT
1803 -P FORWARD DROP
1804 -F FORWARD
1805 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1806 -A FORWARD -i br0 -j ACCEPT
1811 #ifdef TCONFIG_IPV6
1812 if (ipv6_enabled()) {
1813 notice_set("ip6tables", "");
1814 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1815 notice_set("ip6tables", "");
1817 else {
1818 sprintf(s, "%s.error", ip6t_fname);
1819 rename(ip6t_fname, s);
1820 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1821 led(LED_DIAG, 1);
1824 else {
1825 eval("ip6tables", "-F");
1826 eval("ip6tables", "-t", "mangle", "-F");
1828 #endif
1830 if (nvram_get_int("upnp_enable") & 3) {
1831 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1832 killall("miniupnpd", SIGUSR2);
1835 simple_unlock("restrictions");
1836 sched_restrictions();
1837 enable_ip_forward();
1838 #ifdef TCONFIG_IPV6
1839 if (ipv6_enabled()) enable_ip6_forward();
1840 #endif
1842 led(LED_DMZ, dmz_dst(NULL));
1844 #ifdef TCONFIG_IPV6
1845 modprobe_r("nf_conntrack_ipv6");
1846 modprobe_r("ip6t_LOG");
1847 modprobe_r("ip6t_REJECT");
1848 #endif
1849 #ifdef LINUX26
1850 modprobe_r("xt_layer7");
1851 modprobe_r("xt_recent");
1852 modprobe_r("xt_HL");
1853 modprobe_r("xt_length");
1854 modprobe_r("xt_web");
1855 modprobe_r("xt_webmon");
1856 modprobe_r("xt_dscp");
1857 #else
1858 modprobe_r("ipt_layer7");
1859 modprobe_r("ipt_recent");
1860 modprobe_r("ipt_TTL");
1861 modprobe_r("ipt_web");
1862 modprobe_r("ipt_webmon");
1863 modprobe_r("ipt_dscp");
1864 #endif
1865 modprobe_r("ipt_ipp2p");
1867 unlink("/var/webmon/domain");
1868 unlink("/var/webmon/search");
1870 #ifdef TCONFIG_OPENVPN
1871 run_vpn_firewall_scripts();
1872 #endif
1873 run_nvscript("script_fire", NULL, 1);
1875 #ifdef LINUX26
1876 allow_fastnat("firewall", can_enable_fastnat);
1877 try_enabling_fastnat();
1878 #endif
1879 simple_unlock("firewall");
1880 return 0;
1883 int stop_firewall(void)
1885 led(LED_DMZ, 0);
1886 return 0;
1889 #ifdef DEBUG_IPTFILE
1890 void create_test_iptfile(void)
1892 debug_only = 1;
1893 start_firewall();
1894 debug_only = 0;
1896 #endif