firewall: Add PUPNP chain to the nat table - required by the latest miniupnpd.
[tomato.git] / release / src / router / rc / firewall.c
blobfcd94f325f73e2643656138d2cf2d5e1cb77703b
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);
651 // Clamp TCP MSS to PMTU of WAN interface (IPv4 & IPv6)
652 ip46t_write("-I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
654 ip46t_write("COMMIT\n");
657 // -----------------------------------------------------------------------------
658 // NAT
659 // -----------------------------------------------------------------------------
661 static void nat_table(void)
663 char lanaddr[32];
664 char lanmask[32];
665 char lan1addr[32];
666 char lan1mask[32];
667 char lan2addr[32];
668 char lan2mask[32];
669 char lan3addr[32];
670 char lan3mask[32];
671 char dst[64];
672 char src[64];
673 char t[512];
674 char *p, *c;
675 int i;
677 ipt_write("*nat\n"
678 ":PREROUTING ACCEPT [0:0]\n"
679 ":POSTROUTING ACCEPT [0:0]\n"
680 ":OUTPUT ACCEPT [0:0]\n"
681 ":%s - [0:0]\n",
682 chain_wan_prerouting);
684 //2 for nat
685 ipt_qoslimit(2);
687 if (gateway_mode) {
688 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
689 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
690 strlcpy(lan1addr, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr));
691 strlcpy(lan1mask, nvram_safe_get("lan1_netmask"), sizeof(lan1mask));
692 strlcpy(lan2addr, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr));
693 strlcpy(lan2mask, nvram_safe_get("lan2_netmask"), sizeof(lan2mask));
694 strlcpy(lan3addr, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr));
695 strlcpy(lan3mask, nvram_safe_get("lan3_netmask"), sizeof(lan3mask));
698 for (i = 0; i < wanfaces.count; ++i) {
699 if (*(wanfaces.iface[i].name)) {
700 // chain_wan_prerouting
701 if (wanup) {
702 ipt_write("-A PREROUTING -d %s -j %s\n",
703 wanfaces.iface[i].ip, chain_wan_prerouting);
706 // Drop incoming packets which destination IP address is to our LAN side directly
707 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
708 wanfaces.iface[i].name,
709 lanaddr, lanmask); // note: ipt will correct lanaddr
710 if(strcmp(lan1addr,"")!=0)
711 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
712 wanfaces.iface[i].name,
713 lan1addr, lan1mask);
714 if(strcmp(lan2addr,"")!=0)
715 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
716 wanfaces.iface[i].name,
717 lan2addr, lan2mask);
718 if(strcmp(lan3addr,"")!=0)
719 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
720 wanfaces.iface[i].name,
721 lan3addr, lan3mask);
725 if (wanup) {
726 if (nvram_match("dns_intcpt", "1")) {
727 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
728 lanaddr, lanmask,
729 lanaddr, lanmask,
730 lanaddr);
731 if(strcmp(lan1addr,"")!=0)
732 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
733 lan1addr, lan1mask,
734 lan1addr, lan1mask,
735 lan1addr);
736 if(strcmp(lan2addr,"")!=0)
737 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
738 lan2addr, lan2mask,
739 lan2addr, lan2mask,
740 lan2addr);
741 if(strcmp(lan3addr,"")!=0)
742 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
743 lan3addr, lan3mask,
744 lan3addr, lan3mask,
745 lan3addr);
748 // ICMP packets are always redirected to INPUT chains
749 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
752 //force remote access to router if DMZ is enabled - shibby
753 if( (nvram_match("dmz_enable", "1")) && (nvram_match("dmz_ra", "1")) ) {
754 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
755 p = t;
756 do {
757 if ((c = strchr(p, ',')) != NULL) *c = 0;
758 ipt_source(p, src, "ra", NULL);
760 if (remotemanage) {
761 ipt_write("-A %s -p tcp -m tcp %s --dport %s -j DNAT --to-destination %s:%d\n",
762 chain_wan_prerouting, src, nvram_safe_get("http_wanport"), lanaddr, web_lanport);
765 if (nvram_get_int("sshd_remote")) {
766 ipt_write("-A %s %s -p tcp -m tcp --dport %s -j DNAT --to-destination %s:%s\n",
767 chain_wan_prerouting, src, nvram_safe_get("sshd_rport"), lanaddr, nvram_safe_get("sshd_port"));
770 if (!c) break;
771 p = c + 1;
772 } while (*p);
776 ipt_forward(IPT_TABLE_NAT);
777 ipt_triggered(IPT_TABLE_NAT);
780 if (nvram_get_int("upnp_enable") & 3) {
781 ipt_write(":upnp - [0:0]\n");
782 ipt_write(":pupnp - [0:0]\n");
784 for (i = 0; i < wanfaces.count; ++i) {
785 if (*(wanfaces.iface[i].name)) {
786 if (wanup) {
787 // ! for loopback (all) to work
788 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces.iface[i].ip);
790 else {
791 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces.iface[i].name);
797 #ifdef TCONFIG_TOR
798 //TOR
799 if (nvram_match("tor_enable", "1")) {
800 if (nvram_match("tor_iface", "br0")) {
801 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
802 nvram_safe_get("tor_iface"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("tor_transport") );
803 } else if (nvram_match("tor_iface", "br1")) {
804 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
805 nvram_safe_get("tor_iface"), nvram_safe_get("lan1_ipaddr"), nvram_safe_get("lan1_ipaddr"), nvram_safe_get("tor_transport") );
806 } else if (nvram_match("tor_iface", "br2")) {
807 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
808 nvram_safe_get("tor_iface"), nvram_safe_get("lan2_ipaddr"), nvram_safe_get("lan2_ipaddr"), nvram_safe_get("tor_transport") );
809 } else if (nvram_match("tor_iface", "br3")) {
810 ipt_write("-A PREROUTING -i %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
811 nvram_safe_get("tor_iface"), nvram_safe_get("lan3_ipaddr"), nvram_safe_get("lan3_ipaddr"), nvram_safe_get("tor_transport") );
812 } else {
813 strlcpy(t, nvram_safe_get("tor_users"), sizeof(t));
814 p = t;
815 do {
816 if ((c = strchr(p, ',')) != NULL) *c = 0;
818 if (ipt_source_strict(p, src, "tor", NULL))
819 ipt_write("-A PREROUTING %s -p tcp --dport 80 ! -d %s -j DNAT --to-destination %s:%s\n",
820 src, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_ipaddr"), nvram_safe_get("tor_transport") );
822 if (!c) break;
823 p = c + 1;
824 } while (*p);
827 #endif
829 if (wanup) {
830 if (dmz_dst(dst)) {
831 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
832 p = t;
833 do {
834 if ((c = strchr(p, ',')) != NULL) *c = 0;
835 if (ipt_source_strict(p, src, "dmz", NULL))
836 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
837 if (!c) break;
838 p = c + 1;
839 } while (*p);
843 p = "";
844 #ifdef TCONFIG_IPV6
845 switch (get_ipv6_service()) {
846 case IPV6_6IN4:
847 // avoid NATing proto-41 packets when using 6in4 tunnel
848 p = "! -p 41";
849 break;
851 #endif
853 for (i = 0; i < wanfaces.count; ++i) {
854 if (*(wanfaces.iface[i].name)) {
855 if ((!wanup) || (nvram_get_int("ne_snat") != 1))
856 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p, wanfaces.iface[i].name);
857 else
858 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p, wanfaces.iface[i].name, wanfaces.iface[i].ip);
862 char *modem_ipaddr;
863 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
864 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
865 && (!foreach_wif(1, NULL, is_sta)) )
866 ipt_write("-A POSTROUTING -o %s -d %s -j MASQUERADE\n", nvram_safe_get("wan_ifname"), modem_ipaddr);
868 switch (nvram_get_int("nf_loopback")) {
869 case 1: // 1 = forwarded-only
870 case 2: // 2 = disable
871 break;
872 default: // 0 = all (same as block_loopback=0)
873 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
874 lanface,
875 lanaddr, lanmask,
876 lanaddr, lanmask,
877 lanaddr);
878 if (strcmp(lan1face,"")!=0)
879 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
880 lan1face,
881 lan1addr, lan1mask,
882 lan1addr, lan1mask,
883 lan1addr);
884 if (strcmp(lan2face,"")!=0)
885 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
886 lan2face,
887 lan2addr, lan2mask,
888 lan2addr, lan2mask,
889 lan2addr);
890 if (strcmp(lan3face,"")!=0)
891 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
892 lan3face,
893 lan3addr, lan3mask,
894 lan3addr, lan3mask,
895 lan3addr);
896 break;
899 ipt_write("COMMIT\n");
902 // -----------------------------------------------------------------------------
903 // FILTER
904 // -----------------------------------------------------------------------------
906 static void filter_input(void)
908 char s[64];
909 char t[512];
910 char *en;
911 char *sec;
912 char *hit;
913 int n;
914 char *p, *c;
916 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
917 for (n = 0; n < wanfaces.count; ++n) {
918 if (*(wanfaces.iface[n].name)) {
919 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanfaces.iface[n].ip);
920 if (strcmp(lan1face,"")!=0)
921 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face, wanfaces.iface[n].ip);
922 if (strcmp(lan2face,"")!=0)
923 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face, wanfaces.iface[n].ip);
924 if (strcmp(lan3face,"")!=0)
925 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face, wanfaces.iface[n].ip);
930 ipt_write(
931 "-A INPUT -m state --state INVALID -j DROP\n"
932 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
934 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
935 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
937 ? what if the user uses the start button in GUI ?
938 if (nvram_get_int("telnetd_eas"))
939 if (nvram_get_int("sshd_eas"))
941 #ifdef LINUX26
942 modprobe("xt_recent");
943 #else
944 modprobe("ipt_recent");
945 #endif
947 ipt_write(
948 "-N shlimit\n"
949 "-A shlimit -m recent --set --name shlimit\n"
950 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
951 atoi(hit) + 1, sec, chain_in_drop);
953 if (n & 1) {
954 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
955 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
956 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
959 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
962 #ifdef TCONFIG_FTP
963 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
964 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
965 #ifdef LINUX26
966 modprobe("xt_recent");
967 #else
968 modprobe("ipt_recent");
969 #endif
971 ipt_write(
972 "-N ftplimit\n"
973 "-A ftplimit -m recent --set --name ftp\n"
974 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
975 atoi(hit) + 1, sec, chain_in_drop);
976 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
978 #endif
980 ipt_write(
981 "-A INPUT -i lo -j ACCEPT\n"
982 "-A INPUT -i %s -j ACCEPT\n",
983 lanface);
984 if (strcmp(lan1face,"")!=0)
985 ipt_write(
986 "-A INPUT -i %s -j ACCEPT\n",
987 lan1face);
988 if (strcmp(lan2face,"")!=0)
989 ipt_write(
990 "-A INPUT -i %s -j ACCEPT\n",
991 lan2face);
992 if (strcmp(lan3face,"")!=0)
993 ipt_write(
994 "-A INPUT -i %s -j ACCEPT\n",
995 lan3face);
997 #ifdef TCONFIG_IPV6
998 n = get_ipv6_service();
999 switch (n) {
1000 case IPV6_ANYCAST_6TO4:
1001 case IPV6_6IN4:
1002 // Accept ICMP requests from the remote tunnel endpoint
1003 if (n == IPV6_ANYCAST_6TO4)
1004 sprintf(s, "192.88.99.%d", nvram_get_int("ipv6_relay"));
1005 else
1006 strlcpy(s, nvram_safe_get("ipv6_tun_v4end"), sizeof(s));
1007 if (*s && strcmp(s, "0.0.0.0") != 0)
1008 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s, chain_in_accept);
1009 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept);
1010 break;
1012 #endif
1014 // ICMP request from WAN interface
1015 if (nvram_match("block_wan", "0")) {
1016 if (nvram_match("block_wan_limit", "0")) {
1017 // allow ICMP packets to be received
1018 ipt_write("-A INPUT -p icmp -j %s\n", chain_in_accept);
1019 // allow udp traceroute packets
1020 ipt_write("-A INPUT -p udp --dport 33434:33534 -j %s\n", chain_in_accept);
1021 } else {
1022 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
1023 ipt_write("-A INPUT -p icmp -m limit --limit %d/second -j %s\n", nvram_get_int("block_wan_limit_icmp"), chain_in_accept);
1024 // allow udp traceroute packets, but restrict the flow to avoid ping flood attacks
1025 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);
1029 /* Accept incoming packets from broken dhcp servers, which are sending replies
1030 * from addresses other than used for query. This could lead to a lower level
1031 * of security, so allow to disable it via nvram variable.
1033 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
1034 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
1037 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1038 p = t;
1039 do {
1040 if ((c = strchr(p, ',')) != NULL) *c = 0;
1042 if (ipt_source(p, s, "remote management", NULL)) {
1044 if (remotemanage) {
1045 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1046 s, nvram_safe_get("http_wanport"), chain_in_accept);
1049 if (nvram_get_int("sshd_remote")) {
1050 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1051 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1055 if (!c) break;
1056 p = c + 1;
1057 } while (*p);
1059 #ifdef TCONFIG_NGINX //Tomato RAF - Web Server
1060 if (nvram_match("nginx_enable", "1") && nvram_match("nginx_remote", "1"))
1061 ipt_write("-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "nginx_port" ));
1062 #endif
1064 #ifdef TCONFIG_FTP // !!TB - FTP Server
1065 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1066 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1067 p = t;
1068 do {
1069 if ((c = strchr(p, ',')) != NULL) *c = 0;
1070 if (ipt_source(p, s, "ftp", "remote access")) {
1071 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1072 s, nvram_safe_get("ftp_port"), chain_in_accept);
1074 if (!c) break;
1075 p = c + 1;
1076 } while (*p);
1078 #endif
1080 #ifdef TCONFIG_SNMP
1081 if( nvram_match( "snmp_enable", "1" ) && nvram_match("snmp_remote", "1"))
1083 strlcpy(t, nvram_safe_get("snmp_remote_sip"), sizeof(t));
1084 p = t;
1085 do {
1086 if ((c = strchr(p, ',')) != NULL) *c = 0;
1088 if (ipt_source(p, s, "snmp", "remote")) {
1089 ipt_write("-A INPUT -p udp %s --dport %s -j %s\n",
1090 s, nvram_safe_get("snmp_port"), chain_in_accept);
1093 if (!c) break;
1094 p = c + 1;
1095 } while (*p);
1097 #endif
1099 // IGMP query from WAN interface
1100 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1101 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
1102 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
1105 // Routing protocol, RIP, accept
1106 if (nvram_invmatch("dr_wan_rx", "0")) {
1107 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
1110 //BT Client ports from WAN interface
1111 if (nvram_match("bt_enable", "1")) {
1112 ipt_write( "-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "bt_port" ) );
1113 if (nvram_match( "bt_rpc_wan", "1") )
1115 ipt_write( "-A INPUT -p tcp --dport %s -j ACCEPT\n", nvram_safe_get( "bt_port_gui" ) );
1119 // if logging
1120 if (*chain_in_drop == 'l') {
1121 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
1124 // default policy: DROP
1127 static void filter_forward(void)
1129 char dst[64];
1130 char src[64];
1131 char t[512];
1132 char *p, *c;
1133 int i;
1135 #ifdef TCONFIG_IPV6
1136 ip6t_write(
1137 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
1138 #endif
1140 if (nvram_match("cstats_enable", "1")) {
1141 ipt_account();
1144 ip46t_write(
1145 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
1146 lanface, lanface);
1147 if (strcmp(lan1face,"")!=0)
1148 ip46t_write(
1149 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1150 lan1face, lan1face);
1151 if (strcmp(lan2face,"")!=0)
1152 ip46t_write(
1153 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1154 lan2face, lan2face);
1155 if (strcmp(lan3face,"")!=0)
1156 ip46t_write(
1157 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1158 lan3face, lan3face);
1160 char lanAccess[17] = "0000000000000000";
1162 const char *d, *sbr, *saddr, *dbr, *daddr, *desc;
1163 char *nv, *nvp, *b;
1164 int n;
1165 nvp = nv = strdup(nvram_safe_get("lan_access"));
1166 if (nv) {
1167 while ((b = strsep(&nvp, ">")) != NULL) {
1169 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
1171 1 = enabled
1172 0 = src bridge
1173 1.2.3.4 = src addr
1174 1 = dst bridge
1175 5.6.7.8 = dst addr
1176 desc = desc
1178 n = vstrsep(b, "<", &d, &sbr, &saddr, &dbr, &daddr, &desc);
1179 if (*d != '1')
1180 continue;
1181 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4|IPT_V6, 0, "LAN access", desc))
1182 continue;
1183 if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V4|IPT_V6, 0, "LAN access", desc))
1184 continue;
1186 //ipv4 only
1187 ipt_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
1188 "br",
1189 sbr,
1190 "br",
1191 dbr,
1192 src,
1193 dst);
1195 if ((strcmp(src,"")==0) && (strcmp(dst,"")==0))
1196 lanAccess[((*sbr-48)+(*dbr-48)*4)] = '1';
1200 free(nv);
1202 ip46t_write(
1203 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
1205 if (wanup) {
1206 ipt_restrictions();
1208 ipt_layer7_inbound();
1211 ipt_webmon();
1213 ip46t_write(
1214 ":wanin - [0:0]\n"
1215 ":wanout - [0:0]\n"
1216 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1218 char lanN_ifname[] = "lanXX_ifname";
1219 char br;
1220 for(br=0 ; br<=3 ; br++) {
1221 char bridge[2] = "0";
1222 if (br!=0)
1223 bridge[0]+=br;
1224 else
1225 strcpy(bridge, "");
1227 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1228 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1229 char lanN_ifname2[] = "lanXX_ifname";
1230 char br2;
1231 for(br2=0 ; br2<=3 ; br2++) {
1232 if (br==br2) continue;
1234 if (lanAccess[((br)+(br2)*4)] == '1') continue;
1236 char bridge2[2] = "0";
1237 if (br2!=0)
1238 bridge2[0]+=br2;
1239 else
1240 strcpy(bridge2, "");
1242 sprintf(lanN_ifname2, "lan%s_ifname", bridge2);
1243 if (strncmp(nvram_safe_get(lanN_ifname2), "br", 2) == 0) {
1244 ipt_write("-A FORWARD -i %s -o %s -j DROP\n",
1245 nvram_safe_get(lanN_ifname),
1246 nvram_safe_get(lanN_ifname2));
1249 // ip46t_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1253 #ifdef TCONFIG_PPTPD
1254 //Add for pptp server
1255 if (nvram_match("pptpd_enable", "1")) {
1256 ipt_write("-A INPUT -p tcp --dport 1723 -j ACCEPT\n");
1257 ipt_write("-A INPUT -p 47 -j ACCEPT\n");
1259 #endif
1261 #ifdef TCONFIG_IPV6
1262 // Filter out invalid WAN->WAN connections
1263 if (*wan6face)
1264 // 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
1265 ip6t_write("-A FORWARD -o %s -i %s -j %s\n", wan6face, wan6face, chain_in_drop); //shibby - drop connection from WAN -> WAN only
1267 #ifdef LINUX26
1268 modprobe("xt_length");
1269 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1270 #endif
1272 // ICMPv6 rules
1273 for (i = 0; i < sizeof(allowed_icmpv6)/sizeof(int); ++i) {
1274 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[i], chain_in_accept);
1277 //IPv6 IPSec - RFC 6092
1278 if (nvram_match("ipv6_ipsec", "1")) {
1279 if (*wan6face) {
1280 ip6t_write(
1281 "-A FORWARD -i %s -p esp -j ACCEPT\n" //ESP
1282 "-A FORWARD -i %s -p udp --dport 500 -j ACCEPT\n", //IKE
1283 wan6face, wan6face);
1287 //IPv6
1288 if (*wan6face) {
1289 ip6t_write(
1290 "-A FORWARD -i %s -j wanin\n" // generic from wan
1291 "-A FORWARD -o %s -j wanout\n", // generic to wan
1292 wan6face, wan6face);
1294 #endif
1296 //IPv4
1297 for (i = 0; i < wanfaces.count; ++i) {
1298 if (*(wanfaces.iface[i].name)) {
1299 ipt_write(
1300 "-A FORWARD -i %s -j wanin\n" // generic from wan
1301 "-A FORWARD -o %s -j wanout\n", // generic to wan
1302 wanfaces.iface[i].name, wanfaces.iface[i].name);
1306 for(br=0 ; br<=3 ; br++) {
1307 char bridge[2] = "0";
1308 if (br!=0)
1309 bridge[0]+=br;
1310 else
1311 strcpy(bridge, "");
1313 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1314 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1315 ip46t_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1319 #ifdef TCONFIG_IPV6
1320 //IPv6 forward LAN->WAN accept
1321 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wan6face, chain_out_accept);
1323 if (strcmp(lan1face,"")!=0)
1324 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wan6face, chain_out_accept);
1325 if (strcmp(lan2face,"")!=0)
1326 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wan6face, chain_out_accept);
1327 if (strcmp(lan3face,"")!=0)
1328 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wan6face, chain_out_accept);
1329 #endif
1331 // IPv4 only
1332 if (nvram_get_int("upnp_enable") & 3) {
1333 ipt_write(":upnp - [0:0]\n");
1334 for (i = 0; i < wanfaces.count; ++i) {
1335 if (*(wanfaces.iface[i].name)) {
1336 ipt_write("-A FORWARD -i %s -j upnp\n",
1337 wanfaces.iface[i].name);
1342 if (wanup) {
1343 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1344 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
1346 ipt_triggered(IPT_TABLE_FILTER);
1347 ipt_forward(IPT_TABLE_FILTER);
1348 #ifdef TCONFIG_IPV6
1349 ip6t_forward();
1350 #endif
1352 if (dmz_dst(dst)) {
1353 char dmz_ifname[IFNAMSIZ+1];
1354 strlcpy(dmz_ifname, nvram_safe_get("dmz_ifname"), sizeof(dmz_ifname));
1355 if(strcmp(dmz_ifname, "") == 0)
1356 strlcpy(dmz_ifname, lanface, sizeof(lanface));
1357 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
1358 p = t;
1359 do {
1360 if ((c = strchr(p, ',')) != NULL) *c = 0;
1361 if (ipt_source(p, src, "dmz", NULL))
1362 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", dmz_ifname, src, dst, chain_in_accept);
1363 if (!c) break;
1364 p = c + 1;
1365 } while (*p);
1369 // default policy: DROP
1372 static void filter_log(void)
1374 int n;
1375 char limit[128];
1377 n = nvram_get_int("log_limit");
1378 if ((n >= 1) && (n <= 9999)) {
1379 sprintf(limit, "-m limit --limit %d/m", n);
1381 else {
1382 limit[0] = 0;
1385 #ifdef TCONFIG_IPV6
1386 modprobe("ip6t_LOG");
1387 #endif
1388 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
1389 ip46t_write(
1390 ":logdrop - [0:0]\n"
1391 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1392 #ifdef LINUX26
1393 " --log-macdecode"
1394 #endif
1395 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1396 "-A logdrop -j DROP\n"
1397 ":logreject - [0:0]\n"
1398 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1399 #ifdef LINUX26
1400 " --log-macdecode"
1401 #endif
1402 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1403 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1404 limit, limit);
1406 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
1407 ip46t_write(
1408 ":logaccept - [0:0]\n"
1409 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1410 #ifdef LINUX26
1411 " --log-macdecode"
1412 #endif
1413 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1414 "-A logaccept -j ACCEPT\n",
1415 limit);
1419 #ifdef TCONFIG_IPV6
1420 static void filter6_input(void)
1422 char s[128];
1423 char t[512];
1424 char *en;
1425 char *sec;
1426 char *hit;
1427 int n;
1428 char *p, *c;
1430 // RFC-4890, sec. 4.4.1
1431 const int allowed_local_icmpv6[] =
1432 { 130, 131, 132, 133, 134, 135, 136,
1433 141, 142, 143,
1434 148, 149, 151, 152, 153 };
1436 ip6t_write(
1437 "-A INPUT -m rt --rt-type 0 -j %s\n"
1438 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1439 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1440 chain_in_drop);
1442 #ifdef LINUX26
1443 modprobe("xt_length");
1444 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1445 #endif
1447 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
1448 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
1449 #ifdef LINUX26
1450 modprobe("xt_recent");
1451 #else
1452 modprobe("ipt_recent");
1453 #endif
1455 ip6t_write(
1456 "-N shlimit\n"
1457 "-A shlimit -m recent --set --name shlimit\n"
1458 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1459 atoi(hit) + 1, sec, chain_in_drop);
1461 if (n & 1) {
1462 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
1463 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1464 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1467 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"));
1470 #ifdef TCONFIG_FTP
1471 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
1472 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
1473 #ifdef LINUX26
1474 modprobe("xt_recent");
1475 #else
1476 modprobe("ipt_recent");
1477 #endif
1479 ip6t_write(
1480 "-N ftplimit\n"
1481 "-A ftplimit -m recent --set --name ftp\n"
1482 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1483 atoi(hit) + 1, sec, chain_in_drop);
1484 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1486 #endif // TCONFIG_FTP
1488 ip6t_write(
1489 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1490 "-A INPUT -i lo -j ACCEPT\n",
1491 lanface );
1493 switch (get_ipv6_service()) {
1494 case IPV6_ANYCAST_6TO4:
1495 case IPV6_NATIVE_DHCP:
1496 // allow responses from the dhcpv6 server
1497 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept);
1498 break;
1501 // ICMPv6 rules
1502 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
1503 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
1505 for (n = 0; n < sizeof(allowed_local_icmpv6)/sizeof(int); n++) {
1506 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6[n], chain_in_accept);
1509 // Remote Managment
1510 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1511 p = t;
1512 do {
1513 if ((c = strchr(p, ',')) != NULL) *c = 0;
1515 if (ip6t_source(p, s, "remote management", NULL)) {
1517 if (remotemanage) {
1518 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1519 s, nvram_safe_get("http_wanport"), chain_in_accept);
1522 if (nvram_get_int("sshd_remote")) {
1523 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1524 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1528 if (!c) break;
1529 p = c + 1;
1530 } while (*p);
1532 #ifdef TCONFIG_FTP
1533 // FTP server
1534 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1535 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1536 p = t;
1537 do {
1538 if ((c = strchr(p, ',')) != NULL) *c = 0;
1539 if (ip6t_source(p, s, "ftp", "remote access")) {
1540 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1541 s, nvram_safe_get("ftp_port"), chain_in_accept);
1543 if (!c) break;
1544 p = c + 1;
1545 } while (*p);
1547 #endif
1549 // if logging
1550 if (*chain_in_drop == 'l') {
1551 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
1554 // default policy: DROP
1557 #endif
1559 static void filter_table(void)
1561 ip46t_write(
1562 "*filter\n"
1563 ":INPUT DROP [0:0]\n"
1564 ":OUTPUT ACCEPT [0:0]\n"
1567 filter_log();
1569 filter_input();
1570 #ifdef TCONFIG_IPV6
1571 filter6_input();
1572 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop);
1573 #endif
1575 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
1576 ip46t_write(":FORWARD DROP [0:0]\n");
1577 filter_forward();
1579 else {
1580 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1582 ip46t_write("COMMIT\n");
1585 // -----------------------------------------------------------------------------
1587 int start_firewall(void)
1589 DIR *dir;
1590 struct dirent *dirent;
1591 char s[256];
1592 char *c, *wanface;
1593 int n;
1594 int wanproto;
1595 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
1596 #ifdef TCONFIG_IPV6
1597 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
1598 #endif
1600 simple_lock("firewall");
1601 simple_lock("restrictions");
1603 wanup = check_wanup();
1605 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1607 /* NAT performance tweaks
1608 * These values can be overriden later if needed via firewall script
1610 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1611 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1612 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1613 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1614 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1615 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1616 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1617 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1618 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1619 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1620 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1621 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1623 /* DoS-related tweaks */
1624 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1625 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1626 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1628 wanproto = get_wan_proto();
1629 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto == WP_DISABLED || wanproto == WP_STATIC) ? "0" : "1", 0, 0);
1631 #ifdef TCONFIG_EMF
1632 /* Force IGMPv2 due EMF limitations */
1633 if (nvram_get_int("emf_enable")) {
1634 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1635 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1637 #endif
1639 n = nvram_get_int("log_in");
1640 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1641 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1643 n = nvram_get_int("log_out");
1644 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1645 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1646 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1648 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1650 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1651 strlcpy(lan1face, nvram_safe_get("lan1_ifname"), IFNAMSIZ);
1652 strlcpy(lan2face, nvram_safe_get("lan2_ifname"), IFNAMSIZ);
1653 strlcpy(lan3face, nvram_safe_get("lan3_ifname"), IFNAMSIZ);
1655 memcpy(&wanfaces, get_wanfaces(), sizeof(wanfaces));
1656 wanface = wanfaces.iface[0].name;
1657 #ifdef TCONFIG_IPV6
1658 strlcpy(wan6face, get_wan6face(), sizeof(wan6face));
1659 #endif
1661 #ifdef LINUX26
1662 can_enable_fastnat = 1;
1663 #endif
1665 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1666 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1667 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1669 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1670 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1671 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1673 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1674 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1675 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1677 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1678 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1679 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1683 block obviously spoofed IP addresses
1685 rp_filter - BOOLEAN
1686 1 - do source validation by reversed path, as specified in RFC1812
1687 Recommended option for single homed hosts and stub network
1688 routers. Could cause troubles for complicated (not loop free)
1689 networks running a slow unreliable protocol (sort of RIP),
1690 or using static routes.
1691 0 - No source validation.
1693 c = nvram_get("wan_ifname");
1694 /* mcast needs rp filter to be turned off only for non default iface */
1695 if (!(nvram_match("multicast_pass", "1")) || !(nvram_match("udpxy_enable", "1")) || strcmp(wanface, c) == 0) c = NULL;
1697 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1698 while ((dirent = readdir(dir)) != NULL) {
1699 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
1700 f_write_string(s, (c && strcmp(dirent->d_name, c) == 0) ? "0" : "1", 0, 0);
1702 closedir(dir);
1705 remotemanage = 0;
1706 gateway_mode = !nvram_match("wk_mode", "router");
1707 if (gateway_mode) {
1708 /* Remote management */
1709 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1710 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1712 if (nvram_match("remote_mgt_https", "1")) {
1713 web_lanport = nvram_get_int("https_lanport");
1714 if (web_lanport <= 0) web_lanport = 443;
1715 } else {
1716 web_lanport = nvram_get_int("http_lanport");
1717 if (web_lanport <= 0) web_lanport = 80;
1721 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1722 notice_set("iptables", "Unable to create iptables restore file");
1723 simple_unlock("firewall");
1724 return 0;
1727 #ifdef TCONFIG_IPV6
1728 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1729 notice_set("ip6tables", "Unable to create ip6tables restore file");
1730 simple_unlock("firewall");
1731 return 0;
1733 modprobe("nf_conntrack_ipv6");
1734 modprobe("ip6t_REJECT");
1735 #endif
1737 //shibby
1738 //if (nvram_match("imq_enable", "1")) {
1739 // char numdevs[10];
1740 // sprintf(numdevs, "numdevs=%d", nvram_get_int("imq_numdevs"));
1741 // modprobe("imq", numdevs );
1743 modprobe("imq");
1744 #ifdef LINUX26
1745 modprobe("xt_IMQ");
1746 #else
1747 modprobe("ipt_IMQ");
1748 #endif
1749 // }
1752 mangle_table();
1753 nat_table();
1754 filter_table();
1756 fclose(ipt_file);
1757 ipt_file = NULL;
1759 #ifdef TCONFIG_IPV6
1760 fclose(ip6t_file);
1761 ip6t_file = NULL;
1762 #endif
1764 #ifdef DEBUG_IPTFILE
1765 if (debug_only) {
1766 simple_unlock("firewall");
1767 simple_unlock("restrictions");
1768 return 0;
1770 #endif
1772 save_webmon();
1774 if (nvram_get_int("upnp_enable") & 3) {
1775 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1776 if (killall("miniupnpd", SIGUSR2) == 0) {
1777 f_wait_notexists("/etc/upnp/save", 5);
1781 notice_set("iptables", "");
1782 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1783 led(LED_DIAG, 0);
1784 notice_set("iptables", "");
1786 else {
1787 sprintf(s, "%s.error", ipt_fname);
1788 rename(ipt_fname, s);
1789 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1790 led(LED_DIAG, 1);
1794 -P INPUT DROP
1795 -F INPUT
1796 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1797 -A INPUT -i br0 -j ACCEPT
1799 -P FORWARD DROP
1800 -F FORWARD
1801 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1802 -A FORWARD -i br0 -j ACCEPT
1807 #ifdef TCONFIG_IPV6
1808 if (ipv6_enabled()) {
1809 notice_set("ip6tables", "");
1810 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1811 notice_set("ip6tables", "");
1813 else {
1814 sprintf(s, "%s.error", ip6t_fname);
1815 rename(ip6t_fname, s);
1816 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1817 led(LED_DIAG, 1);
1820 else {
1821 eval("ip6tables", "-F");
1822 eval("ip6tables", "-t", "mangle", "-F");
1824 #endif
1826 if (nvram_get_int("upnp_enable") & 3) {
1827 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1828 killall("miniupnpd", SIGUSR2);
1831 simple_unlock("restrictions");
1832 sched_restrictions();
1833 enable_ip_forward();
1834 #ifdef TCONFIG_IPV6
1835 if (ipv6_enabled()) enable_ip6_forward();
1836 #endif
1838 led(LED_DMZ, dmz_dst(NULL));
1840 #ifdef TCONFIG_IPV6
1841 modprobe_r("nf_conntrack_ipv6");
1842 modprobe_r("ip6t_LOG");
1843 modprobe_r("ip6t_REJECT");
1844 #endif
1845 #ifdef LINUX26
1846 modprobe_r("xt_layer7");
1847 modprobe_r("xt_recent");
1848 modprobe_r("xt_HL");
1849 modprobe_r("xt_length");
1850 modprobe_r("xt_web");
1851 modprobe_r("xt_webmon");
1852 modprobe_r("xt_dscp");
1853 #else
1854 modprobe_r("ipt_layer7");
1855 modprobe_r("ipt_recent");
1856 modprobe_r("ipt_TTL");
1857 modprobe_r("ipt_web");
1858 modprobe_r("ipt_webmon");
1859 modprobe_r("ipt_dscp");
1860 #endif
1861 modprobe_r("ipt_ipp2p");
1863 unlink("/var/webmon/domain");
1864 unlink("/var/webmon/search");
1866 #ifdef TCONFIG_OPENVPN
1867 run_vpn_firewall_scripts();
1868 #endif
1870 #ifdef TCONFIG_TINC
1871 run_tinc_firewall_script();
1872 #endif
1874 run_nvscript("script_fire", NULL, 1);
1876 #ifdef LINUX26
1877 allow_fastnat("firewall", can_enable_fastnat);
1878 try_enabling_fastnat();
1879 #endif
1880 simple_unlock("firewall");
1881 return 0;
1884 int stop_firewall(void)
1886 led(LED_DMZ, 0);
1887 return 0;
1890 #ifdef DEBUG_IPTFILE
1891 void create_test_iptfile(void)
1893 debug_only = 1;
1894 start_firewall();
1895 debug_only = 0;
1897 #endif