Add gui for Comcast DSCP fix.
[tomato.git] / release / src / router / rc / firewall.c
blob1e69ab235482a5e3079080fe867d78a4047f45e7
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 if (nvram_match("DSCP_fix_enable", "1")) {
641 #ifdef LINUX26
642 modprobe("xt_DSCP");
643 #else
644 modprobe("ipt_DSCP");
645 #endif
646 ipt_write("-I PREROUTING -i %s -j DSCP --set-dscp 0\n", wanface);
650 ip46t_write("COMMIT\n");
653 // -----------------------------------------------------------------------------
654 // NAT
655 // -----------------------------------------------------------------------------
657 static void nat_table(void)
659 char lanaddr[32];
660 char lanmask[32];
661 char lan1addr[32];
662 char lan1mask[32];
663 char lan2addr[32];
664 char lan2mask[32];
665 char lan3addr[32];
666 char lan3mask[32];
667 char dst[64];
668 char src[64];
669 char t[512];
670 char *p, *c;
671 int i;
673 ipt_write("*nat\n"
674 ":PREROUTING ACCEPT [0:0]\n"
675 ":POSTROUTING ACCEPT [0:0]\n"
676 ":OUTPUT ACCEPT [0:0]\n"
677 ":%s - [0:0]\n",
678 chain_wan_prerouting);
680 //2 for nat
681 ipt_qoslimit(2);
683 if (gateway_mode) {
684 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
685 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
686 strlcpy(lan1addr, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr));
687 strlcpy(lan1mask, nvram_safe_get("lan1_netmask"), sizeof(lan1mask));
688 strlcpy(lan2addr, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr));
689 strlcpy(lan2mask, nvram_safe_get("lan2_netmask"), sizeof(lan2mask));
690 strlcpy(lan3addr, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr));
691 strlcpy(lan3mask, nvram_safe_get("lan3_netmask"), sizeof(lan3mask));
694 for (i = 0; i < wanfaces.count; ++i) {
695 if (*(wanfaces.iface[i].name)) {
696 // chain_wan_prerouting
697 if (wanup) {
698 ipt_write("-A PREROUTING -d %s -j %s\n",
699 wanfaces.iface[i].ip, chain_wan_prerouting);
702 // Drop incoming packets which destination IP address is to our LAN side directly
703 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
704 wanfaces.iface[i].name,
705 lanaddr, lanmask); // note: ipt will correct lanaddr
706 if(strcmp(lan1addr,"")!=0)
707 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
708 wanfaces.iface[i].name,
709 lan1addr, lan1mask);
710 if(strcmp(lan2addr,"")!=0)
711 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
712 wanfaces.iface[i].name,
713 lan2addr, lan2mask);
714 if(strcmp(lan3addr,"")!=0)
715 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
716 wanfaces.iface[i].name,
717 lan3addr, lan3mask);
721 if (wanup) {
722 if (nvram_match("dns_intcpt", "1")) {
723 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
724 lanaddr, lanmask,
725 lanaddr, lanmask,
726 lanaddr);
727 if(strcmp(lan1addr,"")!=0)
728 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
729 lan1addr, lan1mask,
730 lan1addr, lan1mask,
731 lan1addr);
732 if(strcmp(lan2addr,"")!=0)
733 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
734 lan2addr, lan2mask,
735 lan2addr, lan2mask,
736 lan2addr);
737 if(strcmp(lan3addr,"")!=0)
738 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
739 lan3addr, lan3mask,
740 lan3addr, lan3mask,
741 lan3addr);
744 // ICMP packets are always redirected to INPUT chains
745 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
748 //force remote access to router if DMZ is enabled - shibby
749 if( (nvram_match("dmz_enable", "1")) && (nvram_match("dmz_ra", "1")) ) {
750 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
751 p = t;
752 do {
753 if ((c = strchr(p, ',')) != NULL) *c = 0;
754 ipt_source(p, src, "ra", NULL);
756 if (remotemanage) {
757 ipt_write("-A %s -p tcp -m tcp %s --dport %s -j DNAT --to-destination %s:%d\n",
758 chain_wan_prerouting, src, nvram_safe_get("http_wanport"), lanaddr, web_lanport);
761 if (nvram_get_int("sshd_remote")) {
762 ipt_write("-A %s %s -p tcp -m tcp --dport %s -j DNAT --to-destination %s:%s\n",
763 chain_wan_prerouting, src, nvram_safe_get("sshd_rport"), lanaddr, nvram_safe_get("sshd_port"));
766 if (!c) break;
767 p = c + 1;
768 } while (*p);
772 ipt_forward(IPT_TABLE_NAT);
773 ipt_triggered(IPT_TABLE_NAT);
776 if (nvram_get_int("upnp_enable") & 3) {
777 ipt_write(":upnp - [0:0]\n");
779 for (i = 0; i < wanfaces.count; ++i) {
780 if (*(wanfaces.iface[i].name)) {
781 if (wanup) {
782 // ! for loopback (all) to work
783 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces.iface[i].ip);
785 else {
786 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces.iface[i].name);
792 #ifdef TCONFIG_TOR
793 //TOR
794 if (nvram_match("tor_enable", "1")) {
795 if (nvram_match("tor_iface", "br0")) {
796 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
797 nvram_safe_get("tor_iface"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("tor_transport") );
798 } else if (nvram_match("tor_iface", "br1")) {
799 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
800 nvram_safe_get("tor_iface"), nvram_safe_get("lan1_ipaddr"), nvram_safe_get("lan1_ipaddr"), nvram_safe_get("tor_transport") );
801 } else if (nvram_match("tor_iface", "br2")) {
802 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
803 nvram_safe_get("tor_iface"), nvram_safe_get("lan2_ipaddr"), nvram_safe_get("lan2_ipaddr"), nvram_safe_get("tor_transport") );
804 } else if (nvram_match("tor_iface", "br3")) {
805 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
806 nvram_safe_get("tor_iface"), nvram_safe_get("lan3_ipaddr"), nvram_safe_get("lan3_ipaddr"), nvram_safe_get("tor_transport") );
807 } else {
808 strlcpy(t, nvram_safe_get("tor_users"), sizeof(t));
809 p = t;
810 do {
811 if ((c = strchr(p, ',')) != NULL) *c = 0;
813 if (ipt_source_strict(p, src, "tor", NULL))
814 ipt_write("-A PREROUTING %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
815 src, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("tor_transport") );
817 if (!c) break;
818 p = c + 1;
819 } while (*p);
822 #endif
824 if (wanup) {
825 if (dmz_dst(dst)) {
826 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
827 p = t;
828 do {
829 if ((c = strchr(p, ',')) != NULL) *c = 0;
830 if (ipt_source_strict(p, src, "dmz", NULL))
831 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
832 if (!c) break;
833 p = c + 1;
834 } while (*p);
838 p = "";
839 #ifdef TCONFIG_IPV6
840 switch (get_ipv6_service()) {
841 case IPV6_6IN4:
842 // avoid NATing proto-41 packets when using 6in4 tunnel
843 p = "-p ! 41";
844 break;
846 #endif
848 for (i = 0; i < wanfaces.count; ++i) {
849 if (*(wanfaces.iface[i].name)) {
850 if ((!wanup) || (nvram_get_int("ne_snat") != 1))
851 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p, wanfaces.iface[i].name);
852 else
853 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p, wanfaces.iface[i].name, wanfaces.iface[i].ip);
857 char *modem_ipaddr;
858 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
859 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
860 && (!foreach_wif(1, NULL, is_sta)) )
861 ipt_write("-A POSTROUTING -o %s -d %s -j MASQUERADE\n", nvram_safe_get("wan_ifname"), modem_ipaddr);
863 switch (nvram_get_int("nf_loopback")) {
864 case 1: // 1 = forwarded-only
865 case 2: // 2 = disable
866 break;
867 default: // 0 = all (same as block_loopback=0)
868 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
869 lanface,
870 lanaddr, lanmask,
871 lanaddr, lanmask,
872 lanaddr);
873 if (strcmp(lan1face,"")!=0)
874 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
875 lan1face,
876 lan1addr, lan1mask,
877 lan1addr, lan1mask,
878 lan1addr);
879 if (strcmp(lan2face,"")!=0)
880 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
881 lan2face,
882 lan2addr, lan2mask,
883 lan2addr, lan2mask,
884 lan2addr);
885 if (strcmp(lan3face,"")!=0)
886 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
887 lan3face,
888 lan3addr, lan3mask,
889 lan3addr, lan3mask,
890 lan3addr);
891 break;
894 ipt_write("COMMIT\n");
897 // -----------------------------------------------------------------------------
898 // FILTER
899 // -----------------------------------------------------------------------------
901 static void filter_input(void)
903 char s[64];
904 char t[512];
905 char *en;
906 char *sec;
907 char *hit;
908 int n;
909 char *p, *c;
911 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
912 for (n = 0; n < wanfaces.count; ++n) {
913 if (*(wanfaces.iface[n].name)) {
914 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanfaces.iface[n].ip);
915 if (strcmp(lan1face,"")!=0)
916 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face, wanfaces.iface[n].ip);
917 if (strcmp(lan2face,"")!=0)
918 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face, wanfaces.iface[n].ip);
919 if (strcmp(lan3face,"")!=0)
920 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face, wanfaces.iface[n].ip);
925 ipt_write(
926 "-A INPUT -m state --state INVALID -j DROP\n"
927 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
929 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
930 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
932 ? what if the user uses the start button in GUI ?
933 if (nvram_get_int("telnetd_eas"))
934 if (nvram_get_int("sshd_eas"))
936 #ifdef LINUX26
937 modprobe("xt_recent");
938 #else
939 modprobe("ipt_recent");
940 #endif
942 ipt_write(
943 "-N shlimit\n"
944 "-A shlimit -m recent --set --name shlimit\n"
945 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
946 atoi(hit) + 1, sec, chain_in_drop);
948 if (n & 1) {
949 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
950 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
951 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
954 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
957 #ifdef TCONFIG_FTP
958 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
959 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
960 #ifdef LINUX26
961 modprobe("xt_recent");
962 #else
963 modprobe("ipt_recent");
964 #endif
966 ipt_write(
967 "-N ftplimit\n"
968 "-A ftplimit -m recent --set --name ftp\n"
969 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
970 atoi(hit) + 1, sec, chain_in_drop);
971 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
973 #endif
975 ipt_write(
976 "-A INPUT -i lo -j ACCEPT\n"
977 "-A INPUT -i %s -j ACCEPT\n",
978 lanface);
979 if (strcmp(lan1face,"")!=0)
980 ipt_write(
981 "-A INPUT -i %s -j ACCEPT\n",
982 lan1face);
983 if (strcmp(lan2face,"")!=0)
984 ipt_write(
985 "-A INPUT -i %s -j ACCEPT\n",
986 lan2face);
987 if (strcmp(lan3face,"")!=0)
988 ipt_write(
989 "-A INPUT -i %s -j ACCEPT\n",
990 lan3face);
992 #ifdef TCONFIG_IPV6
993 n = get_ipv6_service();
994 switch (n) {
995 case IPV6_ANYCAST_6TO4:
996 case IPV6_6IN4:
997 // Accept ICMP requests from the remote tunnel endpoint
998 if (n == IPV6_ANYCAST_6TO4)
999 sprintf(s, "192.88.99.%d", nvram_get_int("ipv6_relay"));
1000 else
1001 strlcpy(s, nvram_safe_get("ipv6_tun_v4end"), sizeof(s));
1002 if (*s && strcmp(s, "0.0.0.0") != 0)
1003 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s, chain_in_accept);
1004 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept);
1005 break;
1007 #endif
1009 // ICMP request from WAN interface
1010 if (nvram_match("block_wan", "0")) {
1011 if (nvram_match("block_wan_limit", "0")) {
1012 // allow ICMP packets to be received
1013 ipt_write("-A INPUT -p icmp -j %s\n", chain_in_accept);
1014 // allow udp traceroute packets
1015 ipt_write("-A INPUT -p udp --dport 33434:33534 -j %s\n", chain_in_accept);
1016 } else {
1017 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
1018 ipt_write("-A INPUT -p icmp -m limit --limit %d/second -j %s\n", nvram_get_int("block_wan_limit_icmp"), chain_in_accept);
1019 // allow udp traceroute packets, but restrict the flow to avoid ping flood attacks
1020 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);
1024 /* Accept incoming packets from broken dhcp servers, which are sending replies
1025 * from addresses other than used for query. This could lead to a lower level
1026 * of security, so allow to disable it via nvram variable.
1028 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
1029 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
1032 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1033 p = t;
1034 do {
1035 if ((c = strchr(p, ',')) != NULL) *c = 0;
1037 if (ipt_source(p, s, "remote management", NULL)) {
1039 if (remotemanage) {
1040 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1041 s, nvram_safe_get("http_wanport"), chain_in_accept);
1044 if (nvram_get_int("sshd_remote")) {
1045 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1046 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1050 if (!c) break;
1051 p = c + 1;
1052 } while (*p);
1054 #ifdef TCONFIG_NGINX //Tomato RAF - Web Server
1055 if (nvram_match("nginx_enable", "1"))
1056 ipt_write("-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "nginx_port" ));
1057 #endif
1059 #ifdef TCONFIG_FTP // !!TB - FTP Server
1060 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1061 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1062 p = t;
1063 do {
1064 if ((c = strchr(p, ',')) != NULL) *c = 0;
1065 if (ipt_source(p, s, "ftp", "remote access")) {
1066 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1067 s, nvram_safe_get("ftp_port"), chain_in_accept);
1069 if (!c) break;
1070 p = c + 1;
1071 } while (*p);
1073 #endif
1075 #ifdef TCONFIG_SNMP
1076 if( nvram_match( "snmp_enable", "1" ) && nvram_match("snmp_remote", "1"))
1078 strlcpy(t, nvram_safe_get("snmp_remote_sip"), sizeof(t));
1079 p = t;
1080 do {
1081 if ((c = strchr(p, ',')) != NULL) *c = 0;
1083 if (ipt_source(p, s, "snmp", "remote")) {
1084 ipt_write("-A INPUT -p udp %s --dport %s -j %s\n",
1085 s, nvram_safe_get("snmp_port"), chain_in_accept);
1088 if (!c) break;
1089 p = c + 1;
1090 } while (*p);
1092 #endif
1094 // IGMP query from WAN interface
1095 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1096 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
1097 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
1100 // Routing protocol, RIP, accept
1101 if (nvram_invmatch("dr_wan_rx", "0")) {
1102 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
1105 //BT Client ports from WAN interface
1106 if (nvram_match("bt_enable", "1")) {
1107 ipt_write( "-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "bt_port" ) );
1108 if (nvram_match( "bt_rpc_wan", "1") )
1110 ipt_write( "-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "bt_port_gui" ) );
1114 // if logging
1115 if (*chain_in_drop == 'l') {
1116 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
1119 // default policy: DROP
1122 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
1123 static void clampmss(void)
1125 #if 1
1126 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1127 #else
1128 int rmtu = nvram_get_int("wan_run_mtu");
1129 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu - 39);
1130 if (rmtu < 576) {
1131 ipt_write("--clamp-mss-to-pmtu\n");
1133 else {
1134 ipt_write("--set-mss %d\n", rmtu - 40);
1136 #endif
1139 static void filter_forward(void)
1141 char dst[64];
1142 char src[64];
1143 char t[512];
1144 char *p, *c;
1145 int i;
1147 #ifdef TCONFIG_IPV6
1148 ip6t_write(
1149 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
1150 #endif
1152 if (nvram_match("cstats_enable", "1")) {
1153 ipt_account();
1156 ip46t_write(
1157 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
1158 lanface, lanface);
1159 if (strcmp(lan1face,"")!=0)
1160 ip46t_write(
1161 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1162 lan1face, lan1face);
1163 if (strcmp(lan2face,"")!=0)
1164 ip46t_write(
1165 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1166 lan2face, lan2face);
1167 if (strcmp(lan3face,"")!=0)
1168 ip46t_write(
1169 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1170 lan3face, lan3face);
1172 char lanAccess[17] = "0000000000000000";
1174 const char *d, *sbr, *saddr, *dbr, *daddr, *desc;
1175 char *nv, *nvp, *b;
1176 int n;
1177 nvp = nv = strdup(nvram_safe_get("lan_access"));
1178 if (nv) {
1179 while ((b = strsep(&nvp, ">")) != NULL) {
1181 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
1183 1 = enabled
1184 0 = src bridge
1185 1.2.3.4 = src addr
1186 1 = dst bridge
1187 5.6.7.8 = dst addr
1188 desc = desc
1190 n = vstrsep(b, "<", &d, &sbr, &saddr, &dbr, &daddr, &desc);
1191 if (*d != '1')
1192 continue;
1193 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4|IPT_V6, 0, "LAN access", desc))
1194 continue;
1195 if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V4|IPT_V6, 0, "LAN access", desc))
1196 continue;
1198 //ipv4 only
1199 ipt_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
1200 "br",
1201 sbr,
1202 "br",
1203 dbr,
1204 src,
1205 dst);
1207 if ((strcmp(src,"")==0) && (strcmp(dst,"")==0))
1208 lanAccess[((*sbr-48)+(*dbr-48)*4)] = '1';
1212 free(nv);
1214 ip46t_write(
1215 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
1217 // clamp tcp mss to pmtu
1218 clampmss();
1220 if (wanup) {
1221 ipt_restrictions();
1223 ipt_layer7_inbound();
1226 ipt_webmon();
1228 ip46t_write(
1229 ":wanin - [0:0]\n"
1230 ":wanout - [0:0]\n"
1231 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1233 char lanN_ifname[] = "lanXX_ifname";
1234 char br;
1235 for(br=0 ; br<=3 ; br++) {
1236 char bridge[2] = "0";
1237 if (br!=0)
1238 bridge[0]+=br;
1239 else
1240 strcpy(bridge, "");
1242 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1243 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1244 char lanN_ifname2[] = "lanXX_ifname";
1245 char br2;
1246 for(br2=0 ; br2<=3 ; br2++) {
1247 if (br==br2) continue;
1249 if (lanAccess[((br)+(br2)*4)] == '1') continue;
1251 char bridge2[2] = "0";
1252 if (br2!=0)
1253 bridge2[0]+=br2;
1254 else
1255 strcpy(bridge2, "");
1257 sprintf(lanN_ifname2, "lan%s_ifname", bridge2);
1258 if (strncmp(nvram_safe_get(lanN_ifname2), "br", 2) == 0) {
1259 ipt_write("-A FORWARD -i %s -o %s -j DROP\n",
1260 nvram_safe_get(lanN_ifname),
1261 nvram_safe_get(lanN_ifname2));
1264 // ip46t_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1268 #ifdef TCONFIG_PPTPD
1269 //Add for pptp server
1270 if (nvram_match("pptpd_enable", "1")) {
1271 ipt_write("-A INPUT -p tcp --dport 1723 -j ACCEPT\n");
1272 ipt_write("-A INPUT -p 47 -j ACCEPT\n");
1274 #endif
1276 #ifdef TCONFIG_IPV6
1277 // Filter out invalid WAN->WAN connections
1278 if (*wan6face)
1279 // 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
1280 ip6t_write("-A FORWARD -o %s -i %s -j %s\n", wan6face, wan6face, chain_in_drop); //shibby - drop connection from WAN -> WAN only
1282 #ifdef LINUX26
1283 modprobe("xt_length");
1284 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1285 #endif
1287 // ICMPv6 rules
1288 for (i = 0; i < sizeof(allowed_icmpv6)/sizeof(int); ++i) {
1289 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[i], chain_in_accept);
1292 //IPv6
1293 if (*wan6face) {
1294 ip6t_write(
1295 "-A FORWARD -i %s -j wanin\n" // generic from wan
1296 "-A FORWARD -o %s -j wanout\n", // generic to wan
1297 wan6face, wan6face);
1299 #endif
1301 //IPv4
1302 for (i = 0; i < wanfaces.count; ++i) {
1303 if (*(wanfaces.iface[i].name)) {
1304 ipt_write(
1305 "-A FORWARD -i %s -j wanin\n" // generic from wan
1306 "-A FORWARD -o %s -j wanout\n", // generic to wan
1307 wanfaces.iface[i].name, wanfaces.iface[i].name);
1311 for(br=0 ; br<=3 ; br++) {
1312 char bridge[2] = "0";
1313 if (br!=0)
1314 bridge[0]+=br;
1315 else
1316 strcpy(bridge, "");
1318 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1319 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1320 ip46t_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1324 #ifdef TCONFIG_IPV6
1325 //IPv6 forward LAN->WAN accept
1326 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wan6face, chain_out_accept);
1328 if (strcmp(lan1face,"")!=0)
1329 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wan6face, chain_out_accept);
1330 if (strcmp(lan2face,"")!=0)
1331 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wan6face, chain_out_accept);
1332 if (strcmp(lan3face,"")!=0)
1333 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wan6face, chain_out_accept);
1334 #endif
1336 // IPv4 only
1337 if (nvram_get_int("upnp_enable") & 3) {
1338 ipt_write(":upnp - [0:0]\n");
1339 for (i = 0; i < wanfaces.count; ++i) {
1340 if (*(wanfaces.iface[i].name)) {
1341 ipt_write("-A FORWARD -i %s -j upnp\n",
1342 wanfaces.iface[i].name);
1347 if (wanup) {
1348 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1349 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
1351 ipt_triggered(IPT_TABLE_FILTER);
1352 ipt_forward(IPT_TABLE_FILTER);
1353 #ifdef TCONFIG_IPV6
1354 ip6t_forward();
1355 #endif
1357 if (dmz_dst(dst)) {
1358 char dmz_ifname[IFNAMSIZ+1];
1359 strlcpy(dmz_ifname, nvram_safe_get("dmz_ifname"), sizeof(dmz_ifname));
1360 if(strcmp(dmz_ifname, "") == 0)
1361 strlcpy(dmz_ifname, lanface, sizeof(lanface));
1362 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
1363 p = t;
1364 do {
1365 if ((c = strchr(p, ',')) != NULL) *c = 0;
1366 if (ipt_source(p, src, "dmz", NULL))
1367 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", dmz_ifname, src, dst, chain_in_accept);
1368 if (!c) break;
1369 p = c + 1;
1370 } while (*p);
1374 // default policy: DROP
1377 static void filter_log(void)
1379 int n;
1380 char limit[128];
1382 n = nvram_get_int("log_limit");
1383 if ((n >= 1) && (n <= 9999)) {
1384 sprintf(limit, "-m limit --limit %d/m", n);
1386 else {
1387 limit[0] = 0;
1390 #ifdef TCONFIG_IPV6
1391 modprobe("ip6t_LOG");
1392 #endif
1393 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
1394 ip46t_write(
1395 ":logdrop - [0:0]\n"
1396 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1397 #ifdef LINUX26
1398 " --log-macdecode"
1399 #endif
1400 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1401 "-A logdrop -j DROP\n"
1402 ":logreject - [0:0]\n"
1403 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1404 #ifdef LINUX26
1405 " --log-macdecode"
1406 #endif
1407 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1408 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1409 limit, limit);
1411 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
1412 ip46t_write(
1413 ":logaccept - [0:0]\n"
1414 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1415 #ifdef LINUX26
1416 " --log-macdecode"
1417 #endif
1418 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1419 "-A logaccept -j ACCEPT\n",
1420 limit);
1424 #ifdef TCONFIG_IPV6
1425 static void filter6_input(void)
1427 char s[128];
1428 char t[512];
1429 char *en;
1430 char *sec;
1431 char *hit;
1432 int n;
1433 char *p, *c;
1435 // RFC-4890, sec. 4.4.1
1436 const int allowed_local_icmpv6[] =
1437 { 130, 131, 132, 133, 134, 135, 136,
1438 141, 142, 143,
1439 148, 149, 151, 152, 153 };
1441 ip6t_write(
1442 "-A INPUT -m rt --rt-type 0 -j %s\n"
1443 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1444 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1445 chain_in_drop);
1447 #ifdef LINUX26
1448 modprobe("xt_length");
1449 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1450 #endif
1452 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
1453 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
1454 #ifdef LINUX26
1455 modprobe("xt_recent");
1456 #else
1457 modprobe("ipt_recent");
1458 #endif
1460 ip6t_write(
1461 "-N shlimit\n"
1462 "-A shlimit -m recent --set --name shlimit\n"
1463 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1464 atoi(hit) + 1, sec, chain_in_drop);
1466 if (n & 1) {
1467 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
1468 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1469 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1472 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"));
1475 #ifdef TCONFIG_FTP
1476 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
1477 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
1478 #ifdef LINUX26
1479 modprobe("xt_recent");
1480 #else
1481 modprobe("ipt_recent");
1482 #endif
1484 ip6t_write(
1485 "-N ftplimit\n"
1486 "-A ftplimit -m recent --set --name ftp\n"
1487 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1488 atoi(hit) + 1, sec, chain_in_drop);
1489 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1491 #endif // TCONFIG_FTP
1493 ip6t_write(
1494 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1495 "-A INPUT -i lo -j ACCEPT\n",
1496 lanface );
1498 switch (get_ipv6_service()) {
1499 case IPV6_ANYCAST_6TO4:
1500 case IPV6_NATIVE_DHCP:
1501 // allow responses from the dhcpv6 server
1502 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept);
1503 break;
1506 // ICMPv6 rules
1507 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
1508 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
1510 for (n = 0; n < sizeof(allowed_local_icmpv6)/sizeof(int); n++) {
1511 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6[n], chain_in_accept);
1514 // Remote Managment
1515 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1516 p = t;
1517 do {
1518 if ((c = strchr(p, ',')) != NULL) *c = 0;
1520 if (ip6t_source(p, s, "remote management", NULL)) {
1522 if (remotemanage) {
1523 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1524 s, nvram_safe_get("http_wanport"), chain_in_accept);
1527 if (nvram_get_int("sshd_remote")) {
1528 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1529 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1533 if (!c) break;
1534 p = c + 1;
1535 } while (*p);
1537 #ifdef TCONFIG_FTP
1538 // FTP server
1539 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1540 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1541 p = t;
1542 do {
1543 if ((c = strchr(p, ',')) != NULL) *c = 0;
1544 if (ip6t_source(p, s, "ftp", "remote access")) {
1545 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1546 s, nvram_safe_get("ftp_port"), chain_in_accept);
1548 if (!c) break;
1549 p = c + 1;
1550 } while (*p);
1552 #endif
1554 // if logging
1555 if (*chain_in_drop == 'l') {
1556 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
1559 // default policy: DROP
1562 #endif
1564 static void filter_table(void)
1566 ip46t_write(
1567 "*filter\n"
1568 ":INPUT DROP [0:0]\n"
1569 ":OUTPUT ACCEPT [0:0]\n"
1572 filter_log();
1574 filter_input();
1575 #ifdef TCONFIG_IPV6
1576 filter6_input();
1577 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop);
1578 #endif
1580 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
1581 ip46t_write(":FORWARD DROP [0:0]\n");
1582 filter_forward();
1584 else {
1585 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1586 clampmss();
1588 ip46t_write("COMMIT\n");
1591 // -----------------------------------------------------------------------------
1593 int start_firewall(void)
1595 DIR *dir;
1596 struct dirent *dirent;
1597 char s[256];
1598 char *c, *wanface;
1599 int n;
1600 int wanproto;
1601 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
1602 #ifdef TCONFIG_IPV6
1603 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
1604 #endif
1606 simple_lock("firewall");
1607 simple_lock("restrictions");
1609 wanup = check_wanup();
1611 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1613 /* NAT performance tweaks
1614 * These values can be overriden later if needed via firewall script
1616 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1617 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1618 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1619 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1620 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1621 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1622 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1623 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1624 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1625 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1626 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1627 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1629 /* DoS-related tweaks */
1630 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1631 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1632 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1634 wanproto = get_wan_proto();
1635 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto == WP_DISABLED || wanproto == WP_STATIC) ? "0" : "1", 0, 0);
1637 #ifdef TCONFIG_EMF
1638 /* Force IGMPv2 due EMF limitations */
1639 if (nvram_get_int("emf_enable")) {
1640 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1641 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1643 #endif
1645 n = nvram_get_int("log_in");
1646 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1647 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1649 n = nvram_get_int("log_out");
1650 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1651 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1652 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1654 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1656 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1657 strlcpy(lan1face, nvram_safe_get("lan1_ifname"), IFNAMSIZ);
1658 strlcpy(lan2face, nvram_safe_get("lan2_ifname"), IFNAMSIZ);
1659 strlcpy(lan3face, nvram_safe_get("lan3_ifname"), IFNAMSIZ);
1661 memcpy(&wanfaces, get_wanfaces(), sizeof(wanfaces));
1662 wanface = wanfaces.iface[0].name;
1663 #ifdef TCONFIG_IPV6
1664 strlcpy(wan6face, get_wan6face(), sizeof(wan6face));
1665 #endif
1667 #ifdef LINUX26
1668 can_enable_fastnat = 1;
1669 #endif
1671 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1672 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1673 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1675 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1676 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1677 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1679 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1680 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1681 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1683 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1684 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1685 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1689 block obviously spoofed IP addresses
1691 rp_filter - BOOLEAN
1692 1 - do source validation by reversed path, as specified in RFC1812
1693 Recommended option for single homed hosts and stub network
1694 routers. Could cause troubles for complicated (not loop free)
1695 networks running a slow unreliable protocol (sort of RIP),
1696 or using static routes.
1697 0 - No source validation.
1699 c = nvram_get("wan_ifname");
1700 /* mcast needs rp filter to be turned off only for non default iface */
1701 if (!(nvram_match("multicast_pass", "1")) || !(nvram_match("udpxy_enable", "1")) || strcmp(wanface, c) == 0) c = NULL;
1703 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1704 while ((dirent = readdir(dir)) != NULL) {
1705 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
1706 f_write_string(s, (c && strcmp(dirent->d_name, c) == 0) ? "0" : "1", 0, 0);
1708 closedir(dir);
1711 remotemanage = 0;
1712 gateway_mode = !nvram_match("wk_mode", "router");
1713 if (gateway_mode) {
1714 /* Remote management */
1715 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1716 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1718 if (nvram_match("remote_mgt_https", "1")) {
1719 web_lanport = nvram_get_int("https_lanport");
1720 if (web_lanport <= 0) web_lanport = 443;
1721 } else {
1722 web_lanport = nvram_get_int("http_lanport");
1723 if (web_lanport <= 0) web_lanport = 80;
1727 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1728 notice_set("iptables", "Unable to create iptables restore file");
1729 simple_unlock("firewall");
1730 return 0;
1733 #ifdef TCONFIG_IPV6
1734 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1735 notice_set("ip6tables", "Unable to create ip6tables restore file");
1736 simple_unlock("firewall");
1737 return 0;
1739 modprobe("nf_conntrack_ipv6");
1740 modprobe("ip6t_REJECT");
1741 #endif
1743 //shibby
1744 //if (nvram_match("imq_enable", "1")) {
1745 // char numdevs[10];
1746 // sprintf(numdevs, "numdevs=%d", nvram_get_int("imq_numdevs"));
1747 // modprobe("imq", numdevs );
1749 modprobe("imq");
1750 #ifdef LINUX26
1751 modprobe("xt_IMQ");
1752 #else
1753 modprobe("ipt_IMQ");
1754 #endif
1755 // }
1758 mangle_table();
1759 nat_table();
1760 filter_table();
1762 fclose(ipt_file);
1763 ipt_file = NULL;
1765 #ifdef TCONFIG_IPV6
1766 fclose(ip6t_file);
1767 ip6t_file = NULL;
1768 #endif
1770 #ifdef DEBUG_IPTFILE
1771 if (debug_only) {
1772 simple_unlock("firewall");
1773 simple_unlock("restrictions");
1774 return 0;
1776 #endif
1778 save_webmon();
1780 if (nvram_get_int("upnp_enable") & 3) {
1781 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1782 if (killall("miniupnpd", SIGUSR2) == 0) {
1783 f_wait_notexists("/etc/upnp/save", 5);
1787 notice_set("iptables", "");
1788 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1789 led(LED_DIAG, 0);
1790 notice_set("iptables", "");
1792 else {
1793 sprintf(s, "%s.error", ipt_fname);
1794 rename(ipt_fname, s);
1795 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1796 led(LED_DIAG, 1);
1800 -P INPUT DROP
1801 -F INPUT
1802 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1803 -A INPUT -i br0 -j ACCEPT
1805 -P FORWARD DROP
1806 -F FORWARD
1807 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1808 -A FORWARD -i br0 -j ACCEPT
1813 #ifdef TCONFIG_IPV6
1814 if (ipv6_enabled()) {
1815 notice_set("ip6tables", "");
1816 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1817 notice_set("ip6tables", "");
1819 else {
1820 sprintf(s, "%s.error", ip6t_fname);
1821 rename(ip6t_fname, s);
1822 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1823 led(LED_DIAG, 1);
1826 else {
1827 eval("ip6tables", "-F");
1828 eval("ip6tables", "-t", "mangle", "-F");
1830 #endif
1832 if (nvram_get_int("upnp_enable") & 3) {
1833 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1834 killall("miniupnpd", SIGUSR2);
1837 simple_unlock("restrictions");
1838 sched_restrictions();
1839 enable_ip_forward();
1840 #ifdef TCONFIG_IPV6
1841 if (ipv6_enabled()) enable_ip6_forward();
1842 #endif
1844 led(LED_DMZ, dmz_dst(NULL));
1846 #ifdef TCONFIG_IPV6
1847 modprobe_r("nf_conntrack_ipv6");
1848 modprobe_r("ip6t_LOG");
1849 modprobe_r("ip6t_REJECT");
1850 #endif
1851 #ifdef LINUX26
1852 modprobe_r("xt_layer7");
1853 modprobe_r("xt_recent");
1854 modprobe_r("xt_HL");
1855 modprobe_r("xt_length");
1856 modprobe_r("xt_web");
1857 modprobe_r("xt_webmon");
1858 modprobe_r("xt_dscp");
1859 #else
1860 modprobe_r("ipt_layer7");
1861 modprobe_r("ipt_recent");
1862 modprobe_r("ipt_TTL");
1863 modprobe_r("ipt_web");
1864 modprobe_r("ipt_webmon");
1865 modprobe_r("ipt_dscp");
1866 #endif
1867 modprobe_r("ipt_ipp2p");
1869 unlink("/var/webmon/domain");
1870 unlink("/var/webmon/search");
1872 #ifdef TCONFIG_OPENVPN
1873 run_vpn_firewall_scripts();
1874 #endif
1875 run_nvscript("script_fire", NULL, 1);
1877 #ifdef LINUX26
1878 allow_fastnat("firewall", can_enable_fastnat);
1879 try_enabling_fastnat();
1880 #endif
1881 simple_unlock("firewall");
1882 return 0;
1885 int stop_firewall(void)
1887 led(LED_DMZ, 0);
1888 return 0;
1891 #ifdef DEBUG_IPTFILE
1892 void create_test_iptfile(void)
1894 debug_only = 1;
1895 start_firewall();
1896 debug_only = 0;
1898 #endif