Added extrarules to iptables to get UDP request.
[tomato.git] / release / src / router / rc / firewall.c
blobc5593d9dce8b8b30e7e80d6243df6092f48721fe
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 wanface_list_t wanfaces;
33 char lanface[IFNAMSIZ + 1];
34 #ifdef TCONFIG_VLAN
35 char lan1face[IFNAMSIZ + 1];
36 char lan2face[IFNAMSIZ + 1];
37 char lan3face[IFNAMSIZ + 1];
38 #endif
40 #ifdef TCONFIG_IPV6
41 char wan6face[IFNAMSIZ + 1];
42 #endif
43 char lan_cclass[sizeof("xxx.xxx.xxx.") + 1];
44 #ifdef LINUX26
45 static int can_enable_fastnat;
46 #endif
48 #ifdef DEBUG_IPTFILE
49 static int debug_only = 0;
50 #endif
52 static int gateway_mode;
53 static int remotemanage;
54 static int wanup;
56 const char *chain_in_drop;
57 const char *chain_in_accept;
58 const char *chain_out_drop;
59 const char *chain_out_accept;
60 const char *chain_out_reject;
62 const char chain_wan_prerouting[] = "WANPREROUTING";
63 const char ipt_fname[] = "/etc/iptables";
64 FILE *ipt_file;
66 #ifdef TCONFIG_IPV6
67 const char ip6t_fname[] = "/etc/ip6tables";
68 FILE *ip6t_file;
70 // RFC-4890, sec. 4.3.1
71 const int allowed_icmpv6[] = { 1, 2, 3, 4, 128, 129 };
72 #endif
74 static int is_sta(int idx, int unit, int subunit, void *param)
76 return (nvram_match(wl_nvname("mode", unit, subunit), "sta") && (nvram_match(wl_nvname("bss_enabled", unit, subunit), "1")));
80 struct {
81 } firewall_data;
84 // -----------------------------------------------------------------------------
86 #ifdef LINUX26
87 static const char *fastnat_run_dir = "/var/run/fastnat";
89 void allow_fastnat(const char *service, int allow)
91 char p[128];
93 snprintf(p, sizeof(p), "%s/%s", fastnat_run_dir, service);
94 if (allow) {
95 unlink(p);
97 else {
98 mkdir_if_none(fastnat_run_dir);
99 f_write_string(p, "", 0, 0);
103 static inline int fastnat_allowed(void)
105 DIR *dir;
106 struct dirent *dp;
107 int enabled;
109 enabled = !nvram_get_int("qos_enable") && !nvram_get_int("fastnat_disable");
111 if (enabled && (dir = opendir(fastnat_run_dir))) {
112 while ((dp = readdir(dir))) {
113 if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
114 continue;
115 enabled = 0;
116 break;
118 closedir(dir);
121 return (enabled);
124 void try_enabling_fastnat(void)
126 f_write_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_fastnat",
127 fastnat_allowed() ? "1" : "0", 0, 0);
129 #endif
131 void enable_ip_forward(void)
134 ip_forward - BOOLEAN
135 0 - disabled (default)
136 not 0 - enabled
138 Forward Packets between interfaces.
140 This variable is special, its change resets all configuration
141 parameters to their default state (RFC1122 for hosts, RFC1812
142 for routers)
144 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
146 #ifdef TCONFIG_IPV6
147 if (ipv6_enabled()) {
148 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "1", 0, 0);
149 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "1", 0, 0);
151 else {
152 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "0", 0, 0);
153 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "0", 0, 0);
156 #endif
160 // -----------------------------------------------------------------------------
163 static int ip2cclass(char *ipaddr, char *new, int count)
165 int ip[4];
167 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
168 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
173 static int dmz_dst(char *s)
175 struct in_addr ia;
176 char *p;
177 int n;
179 if (nvram_get_int("dmz_enable") <= 0) return 0;
181 p = nvram_safe_get("dmz_ipaddr");
182 if ((ia.s_addr = inet_addr(p)) == (in_addr_t)-1) {
183 if (((n = atoi(p)) <= 0) || (n >= 255)) return 0;
184 if (s) sprintf(s, "%s%d", lan_cclass, n);
185 return 1;
188 if (s) strcpy(s, inet_ntoa(ia));
189 return 1;
192 void ipt_log_unresolved(const char *addr, const char *addrtype, const char *categ, const char *name)
194 char *pre, *post;
196 pre = (name && *name) ? " for \"" : "";
197 post = (name && *name) ? "\"" : "";
199 syslog(LOG_WARNING, "firewall: "
200 "%s: not using %s%s%s%s (could not resolve as valid %s address)",
201 categ, addr, pre, (name) ? : "", post, (addrtype) ? : "IP");
204 int ipt_addr(char *addr, int maxlen, const char *s, const char *dir, int af,
205 int strict, const char *categ, const char *name)
207 char p[INET6_ADDRSTRLEN * 2];
208 int r = 0;
210 if ((s) && (*s) && (*dir))
212 if (sscanf(s, "%[0-9.]-%[0-9.]", p, p) == 2) {
213 snprintf(addr, maxlen, "-m iprange --%s-range %s", dir, s);
214 r = IPT_V4;
216 #ifdef TCONFIG_IPV6
217 else if (sscanf(s, "%[0-9A-Fa-f:]-%[0-9A-Fa-f:]", p, p) == 2) {
218 snprintf(addr, maxlen, "-m iprange --%s-range %s", dir, s);
219 r = IPT_V6;
221 #endif
222 else {
223 snprintf(addr, maxlen, "-%c %s", dir[0], s);
224 if (sscanf(s, "%[^/]/", p)) {
225 #ifdef TCONFIG_IPV6
226 r = host_addrtypes(p, strict ? af : (IPT_V4 | IPT_V6));
227 #else
228 r = host_addrtypes(p, IPT_V4);
229 #endif
233 else
235 *addr = 0;
236 r = (IPT_V4 | IPT_V6);
239 if ((r == 0 || (strict && ((r & af) != af))) && (categ && *categ)) {
240 ipt_log_unresolved(s, categ, name,
241 (af & IPT_V4 & ~r) ? "IPv4" : ((af & IPT_V6 & ~r) ? "IPv6" : NULL));
244 return (r & af);
247 #define ipt_source_strict(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 1, categ, name)
248 #define ipt_source(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 0, categ, name)
249 #define ip6t_source(s, src, categ, name) ipt_addr(src, 128, s, "src", IPT_V6, 0, categ, name)
252 static void get_src(const char *nv, char *src)
254 char *p;
256 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
257 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
259 else {
260 *src = 0;
265 void ipt_write(const char *format, ...)
267 va_list args;
269 va_start(args, format);
270 vfprintf(ipt_file, format, args);
271 va_end(args);
274 void ip6t_write(const char *format, ...)
276 #ifdef TCONFIG_IPV6
277 va_list args;
279 va_start(args, format);
280 vfprintf(ip6t_file, format, args);
281 va_end(args);
282 #endif
285 // -----------------------------------------------------------------------------
287 int ipt_dscp(const char *v, char *opt)
289 unsigned int n;
291 if (*v == 0) {
292 *opt = 0;
293 return 0;
296 n = strtoul(v, NULL, 0);
297 if (n > 63) n = 63;
298 sprintf(opt, " -m dscp --dscp 0x%02X", n);
300 #ifdef LINUX26
301 modprobe("xt_dscp");
302 #else
303 modprobe("ipt_dscp");
304 #endif
305 return 1;
308 // -----------------------------------------------------------------------------
311 int ipt_ipp2p(const char *v, char *opt)
313 int n = atoi(v);
315 if (n == 0) {
316 *opt = 0;
317 return 0;
320 strcpy(opt, "-m ipp2p ");
321 if ((n & 0xFFF) == 0xFFF) {
322 strcat(opt, "--ipp2p");
324 else {
325 // x12
326 if (n & 0x0001) strcat(opt, "--apple ");
327 if (n & 0x0002) strcat(opt, "--ares ");
328 if (n & 0x0004) strcat(opt, "--bit ");
329 if (n & 0x0008) strcat(opt, "--dc ");
330 if (n & 0x0010) strcat(opt, "--edk ");
331 if (n & 0x0020) strcat(opt, "--gnu ");
332 if (n & 0x0040) strcat(opt, "--kazaa ");
333 if (n & 0x0080) strcat(opt, "--mute ");
334 if (n & 0x0100) strcat(opt, "--soul ");
335 if (n & 0x0200) strcat(opt, "--waste ");
336 if (n & 0x0400) strcat(opt, "--winmx ");
337 if (n & 0x0800) strcat(opt, "--xdcc ");
338 #ifdef LINUX26
339 if (n & 0x1000) strcat(opt, "--pp ");
340 if (n & 0x2000) strcat(opt, "--xunlei ");
341 #endif
344 modprobe("ipt_ipp2p");
345 return 1;
349 // -----------------------------------------------------------------------------
352 char **layer7_in;
354 // This L7 matches inbound traffic, caches the results, then the L7 outbound
355 // should read the cached result and set the appropriate marks -- zzz
356 void ipt_layer7_inbound(void)
358 int en, i;
359 char **p;
361 if (!layer7_in) return;
363 en = nvram_match("nf_l7in", "1");
364 if (en) {
365 ipt_write(":L7in - [0:0]\n");
366 for (i = 0; i < wanfaces.count; ++i) {
367 if (*(wanfaces.iface[i].name)) {
368 ipt_write("-A FORWARD -i %s -j L7in\n",
369 wanfaces.iface[i].name);
374 p = layer7_in;
375 while (*p) {
376 if (en) {
377 ipt_write("-A L7in %s -j RETURN\n", *p);
378 #ifdef LINUX26
379 can_enable_fastnat = 0;
380 #endif
382 free(*p);
383 ++p;
385 free(layer7_in);
386 layer7_in = NULL;
389 int ipt_layer7(const char *v, char *opt)
391 char s[128];
392 char *path;
394 *opt = 0;
395 if (*v == 0) return 0;
396 if (strlen(v) > 32) return -1;
398 path = "/etc/l7-extra";
399 sprintf(s, "%s/%s.pat", path, v);
400 if (!f_exists(s)) {
401 path = "/etc/l7-protocols";
402 sprintf(s, "%s/%s.pat", path, v);
403 if (!f_exists(s)) {
404 syslog(LOG_ERR, "L7 %s was not found", v);
405 return -1;
409 sprintf(opt, "-m layer7 --l7dir %s --l7proto %s", path, v);
411 if (nvram_match("nf_l7in", "1")) {
412 if (!layer7_in) layer7_in = calloc(51, sizeof(char *));
413 if (layer7_in) {
414 char **p;
416 p = layer7_in;
417 while (*p) {
418 if (strcmp(*p, opt) == 0) return 1;
419 ++p;
421 if (((p - layer7_in) / sizeof(char *)) < 50) *p = strdup(opt);
425 #ifdef LINUX26
426 modprobe("xt_layer7");
427 #else
428 modprobe("ipt_layer7");
429 #endif
430 return 1;
433 // -----------------------------------------------------------------------------
435 static void ipt_account(void) {
436 struct in_addr ipaddr, netmask, network;
437 char lanN_ifname[] = "lanXX_ifname";
438 char lanN_ipaddr[] = "lanXX_ipaddr";
439 char lanN_netmask[] = "lanXX_netmask";
440 char lanN[] = "lanXX";
441 char netaddrnetmask[] = "255.255.255.255/255.255.255.255 ";
442 char br;
443 // If the IP Address changes, the below rule will cause things to choke, and blocking rules don't get applied
444 // As a workaround, flush the entire FORWARD chain
445 system("iptables -F FORWARD");
447 for(br=0 ; br<=3 ; br++) {
448 char bridge[2] = "0";
449 if (br!=0)
450 bridge[0]+=br;
451 else
452 strcpy(bridge, "");
454 sprintf(lanN_ifname, "lan%s_ifname", bridge);
456 if (strcmp(nvram_safe_get(lanN_ifname), "")!=0) {
458 sprintf(lanN_ipaddr, "lan%s_ipaddr", bridge);
459 sprintf(lanN_netmask, "lan%s_netmask", bridge);
460 sprintf(lanN, "lan%s", bridge);
462 inet_aton(nvram_safe_get(lanN_ipaddr), &ipaddr);
463 inet_aton(nvram_safe_get(lanN_netmask), &netmask);
465 // bitwise AND of ip and netmask gives the network
466 network.s_addr = ipaddr.s_addr & netmask.s_addr;
468 sprintf(netaddrnetmask, "%s/%s", inet_ntoa(network), nvram_safe_get(lanN_netmask));
470 //ipv4 only
471 ipt_write("-A FORWARD -m account --aaddr %s --aname %s\n", netaddrnetmask, lanN);
476 // -----------------------------------------------------------------------------
478 static void save_webmon(void)
480 eval("cp", "/proc/webmon_recent_domains", "/var/webmon/domain");
481 eval("cp", "/proc/webmon_recent_searches", "/var/webmon/search");
484 static void ipt_webmon()
486 int wmtype, clear, i;
487 char t[512];
488 char src[128];
489 char *p, *c;
490 int ok;
492 if (!nvram_get_int("log_wm")) return;
494 #ifdef LINUX26
495 can_enable_fastnat = 0;
496 #endif
497 wmtype = nvram_get_int("log_wmtype");
498 clear = nvram_get_int("log_wmclear");
500 ip46t_write(":monitor - [0:0]\n");
502 // include IPs
503 strlcpy(t, wmtype == 1 ? nvram_safe_get("log_wmip") : "", sizeof(t));
504 p = t;
505 do {
506 if ((c = strchr(p, ',')) != NULL) *c = 0;
508 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
509 #ifdef TCONFIG_IPV6
510 if (*wan6face && (ok & IPT_V6))
511 ip6t_write("-A FORWARD -o %s %s -j monitor\n", wan6face, src);
512 #endif
513 if (ok & IPT_V4) {
514 for (i = 0; i < wanfaces.count; ++i) {
515 if (*(wanfaces.iface[i].name)) {
516 ipt_write("-A FORWARD -o %s %s -j monitor\n",
517 wanfaces.iface[i].name, src);
523 if (!c) break;
524 p = c + 1;
525 } while (*p);
527 // exclude IPs
528 if (wmtype == 2) {
529 strlcpy(t, nvram_safe_get("log_wmip"), sizeof(t));
530 p = t;
531 do {
532 if ((c = strchr(p, ',')) != NULL) *c = 0;
533 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
534 if (*src)
535 ip46t_flagged_write(ok, "-A monitor %s -j RETURN\n", src);
537 if (!c) break;
538 p = c + 1;
539 } while (*p);
542 ip46t_write(
543 "-A monitor -p tcp -m webmon "
544 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
545 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
546 (clear & 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
547 (clear & 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
549 #ifdef LINUX26
550 modprobe("xt_webmon");
551 #else
552 modprobe("ipt_webmon");
553 #endif
557 // -----------------------------------------------------------------------------
558 // MANGLE
559 // -----------------------------------------------------------------------------
561 static void mangle_table(void)
563 int ttl;
564 char *p, *wanface;
566 ip46t_write(
567 "*mangle\n"
568 ":PREROUTING ACCEPT [0:0]\n"
569 ":OUTPUT ACCEPT [0:0]\n");
571 if (wanup) {
573 ipt_qos();
574 //1 for mangle
575 ipt_qoslimit(1);
577 p = nvram_safe_get("nf_ttl");
578 if (strncmp(p, "c:", 2) == 0) {
579 p += 2;
580 ttl = atoi(p);
581 p = (ttl >= 0 && ttl <= 255) ? "set" : NULL;
583 else if ((ttl = atoi(p)) != 0) {
584 if (ttl > 0) {
585 p = "inc";
587 else {
588 ttl = -ttl;
589 p = "dec";
591 if (ttl > 255) p = NULL;
593 else p = NULL;
595 if (p) {
596 #ifdef LINUX26
597 modprobe("xt_HL");
598 #else
599 modprobe("ipt_TTL");
600 #endif
601 // set TTL on primary WAN iface only
602 wanface = wanfaces.iface[0].name;
603 ipt_write(
604 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
605 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
606 wanface, p, ttl,
607 wanface, p, ttl);
608 #ifdef TCONFIG_IPV6
609 // FIXME: IPv6 HL should be configurable separately from TTL.
610 // disable it until GUI setting is implemented.
611 #if 0
612 ip6t_write(
613 "-I PREROUTING -i %s -j HL --hl-%s %d\n"
614 "-I POSTROUTING -o %s -j HL --hl-%s %d\n",
615 wan6face, p, ttl,
616 wan6face, p, ttl);
617 #endif
618 #endif
622 ip46t_write("COMMIT\n");
625 // -----------------------------------------------------------------------------
626 // NAT
627 // -----------------------------------------------------------------------------
629 static void nat_table(void)
631 char lanaddr[32];
632 char lanmask[32];
633 #ifdef TCONFIG_VLAN
634 char lan1addr[32];
635 char lan1mask[32];
636 char lan2addr[32];
637 char lan2mask[32];
638 char lan3addr[32];
639 char lan3mask[32];
640 #endif
641 char dst[64];
642 char src[64];
643 char t[512];
644 char *p, *c;
645 int i;
647 ipt_write("*nat\n"
648 ":PREROUTING ACCEPT [0:0]\n"
649 ":POSTROUTING ACCEPT [0:0]\n"
650 ":OUTPUT ACCEPT [0:0]\n"
651 ":%s - [0:0]\n",
652 chain_wan_prerouting);
654 //2 for nat
655 ipt_qoslimit(2);
657 if (gateway_mode) {
658 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
659 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
660 #ifdef TCONFIG_VLAN
661 strlcpy(lan1addr, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr));
662 strlcpy(lan1mask, nvram_safe_get("lan1_netmask"), sizeof(lan1mask));
663 strlcpy(lan2addr, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr));
664 strlcpy(lan2mask, nvram_safe_get("lan2_netmask"), sizeof(lan2mask));
665 strlcpy(lan3addr, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr));
666 strlcpy(lan3mask, nvram_safe_get("lan3_netmask"), sizeof(lan3mask));
667 #endif
669 for (i = 0; i < wanfaces.count; ++i) {
670 if (*(wanfaces.iface[i].name)) {
671 // chain_wan_prerouting
672 if (wanup) {
673 ipt_write("-A PREROUTING -d %s -j %s\n",
674 wanfaces.iface[i].ip, chain_wan_prerouting);
677 // Drop incoming packets which destination IP address is to our LAN side directly
678 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
679 wanfaces.iface[i].name,
680 lanaddr, lanmask); // note: ipt will correct lanaddr
681 #ifdef TCONFIG_VLAN
682 if(strcmp(lan1addr,"")!=0)
683 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
684 wanfaces.iface[i].name,
685 lan1addr, lan1mask);
686 if(strcmp(lan2addr,"")!=0)
687 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
688 wanfaces.iface[i].name,
689 lan2addr, lan2mask);
690 if(strcmp(lan3addr,"")!=0)
691 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
692 wanfaces.iface[i].name,
693 lan3addr, lan3mask);
694 #endif
698 if (wanup) {
699 if (nvram_match("dns_intcpt", "1")) {
700 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
701 lanaddr, lanmask,
702 lanaddr, lanmask,
703 lanaddr);
704 #ifdef TCONFIG_VLAN
705 if(strcmp(lan1addr,"")!=0)
706 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
707 lan1addr, lan1mask,
708 lan1addr, lan1mask,
709 lan1addr);
710 if(strcmp(lan2addr,"")!=0)
711 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
712 lan2addr, lan2mask,
713 lan2addr, lan2mask,
714 lan2addr);
715 if(strcmp(lan3addr,"")!=0)
716 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
717 lan3addr, lan3mask,
718 lan3addr, lan3mask,
719 lan3addr);
720 #endif
723 #ifdef TCONFIG_NGINX
724 if (wanup) {
725 if (nvram_match("nginx_enable", "1")) {
726 ipt_write("-A PREROUTING -p tcp -s %s/%s ! -d %s/%s --dport 80 -j DNAT --to-destination %s\n",
727 lanaddr, lanmask,
728 lanaddr, lanmask,
729 lanaddr);
730 ipt_write("-A PREROUTING -p tcp -s %s/%s ! -d %s/%s --dport 44380 -j DNAT --to-destination %s\n",
731 lanaddr, lanmask,
732 lanaddr, lanmask,
733 lanaddr);
736 #endif
738 // ICMP packets are always redirected to INPUT chains
739 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
741 ipt_forward(IPT_TABLE_NAT);
742 ipt_triggered(IPT_TABLE_NAT);
745 if (nvram_get_int("upnp_enable") & 3) {
746 ipt_write(":upnp - [0:0]\n");
748 for (i = 0; i < wanfaces.count; ++i) {
749 if (*(wanfaces.iface[i].name)) {
750 if (wanup) {
751 // ! for loopback (all) to work
752 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces.iface[i].ip);
754 else {
755 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces.iface[i].name);
761 if (wanup) {
762 if (dmz_dst(dst)) {
763 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
764 p = t;
765 do {
766 if ((c = strchr(p, ',')) != NULL) *c = 0;
767 if (ipt_source_strict(p, src, "dmz", NULL))
768 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
769 if (!c) break;
770 p = c + 1;
771 } while (*p);
775 p = "";
776 #ifdef TCONFIG_IPV6
777 switch (get_ipv6_service()) {
778 case IPV6_6IN4:
779 // avoid NATing proto-41 packets when using 6in4 tunnel
780 p = "-p ! 41";
781 break;
783 #endif
785 for (i = 0; i < wanfaces.count; ++i) {
786 if (*(wanfaces.iface[i].name)) {
787 if ((!wanup) || (nvram_get_int("ne_snat") != 1))
788 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p, wanfaces.iface[i].name);
789 else
790 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p, wanfaces.iface[i].name, wanfaces.iface[i].ip);
794 char *modem_ipaddr;
795 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
796 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
797 && (!foreach_wif(1, NULL, is_sta)) )
798 ipt_write("-A POSTROUTING -o %s -d %s -j MASQUERADE\n", nvram_safe_get("wan_ifname"), modem_ipaddr);
800 switch (nvram_get_int("nf_loopback")) {
801 case 1: // 1 = forwarded-only
802 case 2: // 2 = disable
803 break;
804 default: // 0 = all (same as block_loopback=0)
805 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
806 lanface,
807 lanaddr, lanmask,
808 lanaddr, lanmask,
809 lanaddr);
810 #ifdef TCONFIG_VLAN
811 if (strcmp(lan1face,"")!=0)
812 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
813 lan1face,
814 lan1addr, lan1mask,
815 lan1addr, lan1mask,
816 lan1addr);
817 if (strcmp(lan2face,"")!=0)
818 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
819 lan2face,
820 lan2addr, lan2mask,
821 lan2addr, lan2mask,
822 lan2addr);
823 if (strcmp(lan3face,"")!=0)
824 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
825 lan3face,
826 lan3addr, lan3mask,
827 lan3addr, lan3mask,
828 lan3addr);
829 #endif
830 break;
833 ipt_write("COMMIT\n");
836 // -----------------------------------------------------------------------------
837 // FILTER
838 // -----------------------------------------------------------------------------
840 static void filter_input(void)
842 char s[64];
843 char t[512];
844 char *en;
845 char *sec;
846 char *hit;
847 int n;
848 char *p, *c;
850 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
851 for (n = 0; n < wanfaces.count; ++n) {
852 if (*(wanfaces.iface[n].name)) {
853 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanfaces.iface[n].ip);
854 #ifdef TCONFIG_VLAN
855 if (strcmp(lan1face,"")!=0)
856 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face, wanfaces.iface[n].ip);
857 if (strcmp(lan2face,"")!=0)
858 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face, wanfaces.iface[n].ip);
859 if (strcmp(lan3face,"")!=0)
860 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face, wanfaces.iface[n].ip);
861 #endif
866 ipt_write(
867 "-A INPUT -m state --state INVALID -j DROP\n"
868 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
870 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
871 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
873 ? what if the user uses the start button in GUI ?
874 if (nvram_get_int("telnetd_eas"))
875 if (nvram_get_int("sshd_eas"))
877 #ifdef LINUX26
878 modprobe("xt_recent");
879 #else
880 modprobe("ipt_recent");
881 #endif
883 ipt_write(
884 "-N shlimit\n"
885 "-A shlimit -m recent --set --name shlimit\n"
886 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
887 atoi(hit) + 1, sec, chain_in_drop);
889 if (n & 1) {
890 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
891 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
892 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
895 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
898 #ifdef TCONFIG_FTP
899 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
900 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
901 #ifdef LINUX26
902 modprobe("xt_recent");
903 #else
904 modprobe("ipt_recent");
905 #endif
907 ipt_write(
908 "-N ftplimit\n"
909 "-A ftplimit -m recent --set --name ftp\n"
910 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
911 atoi(hit) + 1, sec, chain_in_drop);
912 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
914 #endif
916 ipt_write(
917 "-A INPUT -i lo -j ACCEPT\n"
918 "-A INPUT -i %s -j ACCEPT\n",
919 lanface);
921 #ifdef TCONFIG_VLAN
922 if (strcmp(lan1face,"")!=0)
923 ipt_write(
924 "-A INPUT -i %s -j ACCEPT\n",
925 lan1face);
926 if (strcmp(lan2face,"")!=0)
927 ipt_write(
928 "-A INPUT -i %s -j ACCEPT\n",
929 lan2face);
930 if (strcmp(lan3face,"")!=0)
931 ipt_write(
932 "-A INPUT -i %s -j ACCEPT\n",
933 lan3face);
934 #endif
936 #ifdef TCONFIG_IPV6
937 n = get_ipv6_service();
938 switch (n) {
939 case IPV6_ANYCAST_6TO4:
940 case IPV6_6IN4:
941 // Accept ICMP requests from the remote tunnel endpoint
942 if (n == IPV6_ANYCAST_6TO4)
943 sprintf(s, "192.88.99.%d", nvram_get_int("ipv6_relay"));
944 else
945 strlcpy(s, nvram_safe_get("ipv6_tun_v4end"), sizeof(s));
946 if (*s && strcmp(s, "0.0.0.0") != 0)
947 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s, chain_in_accept);
948 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept);
949 break;
951 #endif
953 // ICMP request from WAN interface
954 if (nvram_match("block_wan", "0")) {
955 if (nvram_match("block_wan_limit", "0")) {
956 // allow ICMP packets to be received
957 ipt_write("-A INPUT -p icmp -j %s\n", chain_in_accept);
958 // allow udp traceroute packets
959 ipt_write("-A INPUT -p udp --dport 33434:33534 -j %s\n", chain_in_accept);
960 } else {
961 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
962 ipt_write("-A INPUT -p icmp -m limit --limit %d/second -j %s\n", nvram_get_int("block_wan_limit_icmp"), chain_in_accept);
963 // allow udp traceroute packets, but restrict the flow to avoid ping flood attacks
964 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);
968 /* Accept incoming packets from broken dhcp servers, which are sending replies
969 * from addresses other than used for query. This could lead to a lower level
970 * of security, so allow to disable it via nvram variable.
972 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
973 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
976 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
977 p = t;
978 do {
979 if ((c = strchr(p, ',')) != NULL) *c = 0;
981 if (ipt_source(p, s, "remote management", NULL)) {
983 if (remotemanage) {
984 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
985 s, nvram_safe_get("http_wanport"), chain_in_accept);
988 if (nvram_get_int("sshd_remote")) {
989 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
990 s, nvram_safe_get("sshd_rport"), chain_in_accept);
995 #ifdef TCONFIG_NGINX
996 if (nvram_get_int("nginx_enable")) {
997 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %s -j %s\n",
998 s, nvram_safe_get("lan_ipaddr"), nvram_safe_get("nginx_port"), chain_in_accept);
1000 #endif
1002 if (!c) break;
1003 p = c + 1;
1004 } while (*p);
1006 #ifdef TCONFIG_FTP // !!TB - FTP Server
1007 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1008 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1009 p = t;
1010 do {
1011 if ((c = strchr(p, ',')) != NULL) *c = 0;
1012 if (ipt_source(p, s, "ftp", "remote access")) {
1013 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1014 s, nvram_safe_get("ftp_port"), chain_in_accept);
1016 if (!c) break;
1017 p = c + 1;
1018 } while (*p);
1020 #endif
1022 #ifdef TCONFIG_SNMP
1023 if( nvram_match( "snmp_enable", "1" ) && nvram_match("snmp_remote", "1"))
1025 strlcpy(t, nvram_safe_get("snmp_remote_sip"), sizeof(t));
1026 p = t;
1027 do {
1028 if ((c = strchr(p, ',')) != NULL) *c = 0;
1030 if (ipt_source(p, s, "snmp", "remote")) {
1031 ipt_write("-A INPUT -p udp %s --dport %s -j %s\n",
1032 s, nvram_safe_get("snmp_port"), chain_in_accept);
1035 if (!c) break;
1036 p = c + 1;
1037 } while (*p);
1039 #endif
1041 // IGMP query from WAN interface
1042 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1043 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
1044 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
1047 // Routing protocol, RIP, accept
1048 if (nvram_invmatch("dr_wan_rx", "0")) {
1049 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
1052 // if logging
1053 if (*chain_in_drop == 'l') {
1054 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
1057 // default policy: DROP
1060 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
1061 static void clampmss(void)
1063 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1064 #ifdef TCONFIG_IPV6
1065 switch (get_ipv6_service()) {
1066 case IPV6_ANYCAST_6TO4:
1067 case IPV6_6IN4:
1068 ip6t_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1069 break;
1071 #endif
1074 static void filter_forward(void)
1076 char dst[64];
1077 char src[64];
1078 char t[512];
1079 char *p, *c;
1080 int i;
1082 if (nvram_match("cstats_enable", "1")) {
1083 ipt_account();
1086 #ifdef TCONFIG_IPV6
1087 ip6t_write(
1088 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
1089 #endif
1091 ip46t_write(
1092 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
1093 lanface, lanface);
1094 #ifdef TCONFIG_VLAN
1095 if (strcmp(lan1face,"")!=0)
1096 ip46t_write(
1097 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1098 lan1face, lan1face);
1099 if (strcmp(lan2face,"")!=0)
1100 ip46t_write(
1101 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1102 lan2face, lan2face);
1103 if (strcmp(lan3face,"")!=0)
1104 ip46t_write(
1105 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1106 lan3face, lan3face);
1108 char lanAccess[17] = "0000000000000000";
1109 const char *d, *sbr, *saddr, *dbr, *daddr, *desc;
1110 char *nv, *nvp, *b;
1111 int n;
1112 nvp = nv = strdup(nvram_safe_get("lan_access"));
1113 if (nv) {
1114 while ((b = strsep(&nvp, ">")) != NULL) {
1116 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
1118 1 = enabled
1119 0 = src bridge
1120 1.2.3.4 = src addr
1121 1 = dst bridge
1122 5.6.7.8 = dst addr
1123 desc = desc
1125 n = vstrsep(b, "<", &d, &sbr, &saddr, &dbr, &daddr, &desc);
1126 if (*d != '1')
1127 continue;
1128 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4|IPT_V6, 0, "LAN access", desc))
1129 continue;
1130 if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V4|IPT_V6, 0, "LAN access", desc))
1131 continue;
1133 //ipv4 only
1134 ipt_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
1135 "br",
1136 sbr,
1137 "br",
1138 dbr,
1139 src,
1140 dst);
1142 if ((strcmp(src,"")==0) && (strcmp(dst,"")==0))
1143 lanAccess[((*sbr-48)+(*dbr-48)*4)] = '1';
1147 free(nv);
1148 #endif
1150 ip46t_write(
1151 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
1153 // clamp tcp mss to pmtu
1154 clampmss();
1156 if (wanup) {
1157 ipt_restrictions();
1159 ipt_layer7_inbound();
1162 ipt_webmon();
1164 ip46t_write(
1165 ":wanin - [0:0]\n"
1166 ":wanout - [0:0]\n"
1167 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1169 #ifdef TCONFIG_VLAN
1170 char lanN_ifname[] = "lanXX_ifname";
1171 char br;
1172 for(br=0 ; br<=3 ; br++) {
1173 char bridge[2] = "0";
1174 if (br!=0)
1175 bridge[0]+=br;
1176 else
1177 strcpy(bridge, "");
1179 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1180 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1181 char lanN_ifname2[] = "lanXX_ifname";
1182 char br2;
1183 for(br2=0 ; br2<=3 ; br2++) {
1184 if (br==br2) continue;
1186 if (lanAccess[((br)+(br2)*4)] == '1') continue;
1188 char bridge2[2] = "0";
1189 if (br2!=0)
1190 bridge2[0]+=br2;
1191 else
1192 strcpy(bridge2, "");
1194 sprintf(lanN_ifname2, "lan%s_ifname", bridge2);
1195 if (strncmp(nvram_safe_get(lanN_ifname2), "br", 2) == 0) {
1196 ip46t_write("-A FORWARD -i %s -o %s -j DROP\n",
1197 nvram_safe_get(lanN_ifname),
1198 nvram_safe_get(lanN_ifname2));
1201 // ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1204 #endif
1206 #ifdef TCONFIG_PPTPD
1207 //Add for pptp server
1208 if (nvram_match("pptpd_enable", "1")) {
1209 ipt_write("-A INPUT -p tcp --dport 1723 -j ACCEPT\n");
1210 ipt_write("-A INPUT -p 47 -j ACCEPT\n");
1212 #endif
1214 #ifdef TCONFIG_IPV6
1215 // Filter out invalid WAN->WAN connections
1216 if (*wan6face)
1217 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face, lanface, chain_in_drop);
1219 #ifdef LINUX26
1220 modprobe("xt_length");
1221 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1222 #endif
1224 // ICMPv6 rules
1225 for (i = 0; i < sizeof(allowed_icmpv6)/sizeof(int); ++i) {
1226 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[i], chain_in_accept);
1229 //IPv6
1230 if (*wan6face) {
1231 ip6t_write(
1232 "-A FORWARD -i %s -j wanin\n" // generic from wan
1233 "-A FORWARD -o %s -j wanout\n", // generic to wan
1234 wan6face, wan6face);
1236 #endif
1238 //IPv4
1239 for (i = 0; i < wanfaces.count; ++i) {
1240 if (*(wanfaces.iface[i].name)) {
1241 ipt_write(
1242 "-A FORWARD -i %s -j wanin\n" // generic from wan
1243 "-A FORWARD -o %s -j wanout\n", // generic to wan
1244 wanfaces.iface[i].name, wanfaces.iface[i].name);
1248 #ifdef TCONFIG_VLAN
1249 for(br=0 ; br<=3 ; br++) {
1250 char bridge[2] = "0";
1251 if (br!=0)
1252 bridge[0]+=br;
1253 else
1254 strcpy(bridge, "");
1256 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1257 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1258 ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1261 #else
1262 ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1263 #endif
1265 // #ifdef TCONFIG_VLAN
1266 /* for (i = 0; i < wanfaces.count; ++i) {
1267 if (*(wanfaces.iface[i].name)) {
1268 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wanfaces.iface[i].name, chain_out_accept);
1269 if (strcmp(lan1face,"")!=0)
1270 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wanfaces.iface[i].name, chain_out_accept);
1271 if (strcmp(lan2face,"")!=0)
1272 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wanfaces.iface[i].name, chain_out_accept);
1273 if (strcmp(lan3face,"")!=0)
1274 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wanfaces.iface[i].name, chain_out_accept);
1278 // #else
1279 // ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1280 // #endif
1282 #ifdef TCONFIG_IPV6
1283 //IPv6 forward LAN->WAN accept
1284 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wan6face, chain_out_accept);
1285 #ifdef TCONFIG_VLAN
1286 if (strcmp(lan1face,"")!=0)
1287 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wan6face, chain_out_accept);
1288 if (strcmp(lan2face,"")!=0)
1289 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wan6face, chain_out_accept);
1290 if (strcmp(lan3face,"")!=0)
1291 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wan6face, chain_out_accept);
1292 #endif
1293 #endif
1295 // IPv4 only
1296 if (nvram_get_int("upnp_enable") & 3) {
1297 ipt_write(":upnp - [0:0]\n");
1298 for (i = 0; i < wanfaces.count; ++i) {
1299 if (*(wanfaces.iface[i].name)) {
1300 ipt_write("-A FORWARD -i %s -j upnp\n",
1301 wanfaces.iface[i].name);
1306 if (wanup) {
1307 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1308 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
1310 ipt_triggered(IPT_TABLE_FILTER);
1311 ipt_forward(IPT_TABLE_FILTER);
1312 #ifdef TCONFIG_IPV6
1313 ip6t_forward();
1314 #endif
1316 if (dmz_dst(dst)) {
1317 #ifdef TCONFIG_VLAN
1318 char dmz_ifname[IFNAMSIZ+1];
1319 strlcpy(dmz_ifname, nvram_safe_get("dmz_ifname"), sizeof(dmz_ifname));
1320 if(strcmp(dmz_ifname, "") == 0)
1321 strlcpy(dmz_ifname, lanface, sizeof(lanface));
1322 #endif
1323 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
1324 p = t;
1325 do {
1326 if ((c = strchr(p, ',')) != NULL) *c = 0;
1327 if (ipt_source_strict(p, src, "dmz", NULL))
1328 #ifdef TCONFIG_VLAN
1329 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", dmz_ifname, src, dst, chain_in_accept);
1330 #else
1331 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface, src, dst, chain_in_accept);
1332 #endif
1333 if (!c) break;
1334 p = c + 1;
1335 } while (*p);
1339 // default policy: DROP
1342 static void filter_log(void)
1344 int n;
1345 char limit[128];
1347 n = nvram_get_int("log_limit");
1348 if ((n >= 1) && (n <= 9999)) {
1349 sprintf(limit, "-m limit --limit %d/m", n);
1351 else {
1352 limit[0] = 0;
1355 #ifdef TCONFIG_IPV6
1356 modprobe("ip6t_LOG");
1357 #endif
1358 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
1359 ip46t_write(
1360 ":logdrop - [0:0]\n"
1361 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1362 #ifdef LINUX26
1363 " --log-macdecode"
1364 #endif
1365 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1366 "-A logdrop -j DROP\n"
1367 ":logreject - [0:0]\n"
1368 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1369 #ifdef LINUX26
1370 " --log-macdecode"
1371 #endif
1372 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1373 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1374 limit, limit);
1376 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
1377 ip46t_write(
1378 ":logaccept - [0:0]\n"
1379 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1380 #ifdef LINUX26
1381 " --log-macdecode"
1382 #endif
1383 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1384 "-A logaccept -j ACCEPT\n",
1385 limit);
1389 #ifdef TCONFIG_IPV6
1390 static void filter6_input(void)
1392 char s[128];
1393 char t[512];
1394 char *en;
1395 char *sec;
1396 char *hit;
1397 int n;
1398 char *p, *c;
1400 // RFC-4890, sec. 4.4.1
1401 const int allowed_local_icmpv6[] =
1402 { 130, 131, 132, 133, 134, 135, 136,
1403 141, 142, 143,
1404 148, 149, 151, 152, 153 };
1406 ip6t_write(
1407 "-A INPUT -m rt --rt-type 0 -j %s\n"
1408 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1409 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1410 chain_in_drop);
1412 #ifdef LINUX26
1413 modprobe("xt_length");
1414 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1415 #endif
1417 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
1418 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
1419 #ifdef LINUX26
1420 modprobe("xt_recent");
1421 #else
1422 modprobe("ipt_recent");
1423 #endif
1425 ip6t_write(
1426 "-N shlimit\n"
1427 "-A shlimit -m recent --set --name shlimit\n"
1428 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1429 atoi(hit) + 1, sec, chain_in_drop);
1431 if (n & 1) {
1432 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
1433 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1434 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1437 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"));
1440 #ifdef TCONFIG_FTP
1441 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
1442 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
1443 #ifdef LINUX26
1444 modprobe("xt_recent");
1445 #else
1446 modprobe("ipt_recent");
1447 #endif
1449 ip6t_write(
1450 "-N ftplimit\n"
1451 "-A ftplimit -m recent --set --name ftp\n"
1452 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1453 atoi(hit) + 1, sec, chain_in_drop);
1454 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1456 #endif // TCONFIG_FTP
1458 ip6t_write(
1459 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1460 "-A INPUT -i lo -j ACCEPT\n",
1461 lanface );
1463 switch (get_ipv6_service()) {
1464 case IPV6_ANYCAST_6TO4:
1465 case IPV6_NATIVE_DHCP:
1466 // allow responses from the dhcpv6 server
1467 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept);
1468 break;
1471 // ICMPv6 rules
1472 const int allowed_icmpv6[6] = { 1, 2, 3, 4, 128, 129 };
1473 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
1474 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
1476 for (n = 0; n < sizeof(allowed_local_icmpv6)/sizeof(int); n++) {
1477 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6[n], chain_in_accept);
1480 // Remote Managment
1481 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1482 p = t;
1483 do {
1484 if ((c = strchr(p, ',')) != NULL) *c = 0;
1486 if (ip6t_source(p, s, "remote management", NULL)) {
1488 if (remotemanage) {
1489 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1490 s, nvram_safe_get("http_wanport"), chain_in_accept);
1493 if (nvram_get_int("sshd_remote")) {
1494 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1495 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1499 if (!c) break;
1500 p = c + 1;
1501 } while (*p);
1503 #ifdef TCONFIG_FTP
1504 // FTP server
1505 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1506 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1507 p = t;
1508 do {
1509 if ((c = strchr(p, ',')) != NULL) *c = 0;
1510 if (ip6t_source(p, s, "ftp", "remote access")) {
1511 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1512 s, nvram_safe_get("ftp_port"), chain_in_accept);
1514 if (!c) break;
1515 p = c + 1;
1516 } while (*p);
1518 #endif
1520 // if logging
1521 if (*chain_in_drop == 'l') {
1522 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
1525 // default policy: DROP
1528 #endif
1530 static void filter_table(void)
1532 ip46t_write(
1533 "*filter\n"
1534 ":INPUT DROP [0:0]\n"
1535 ":OUTPUT ACCEPT [0:0]\n"
1538 filter_log();
1540 filter_input();
1541 #ifdef TCONFIG_IPV6
1542 filter6_input();
1543 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop);
1544 #endif
1546 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
1547 ip46t_write(":FORWARD DROP [0:0]\n");
1548 filter_forward();
1550 else {
1551 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1552 clampmss();
1554 ip46t_write("COMMIT\n");
1557 // -----------------------------------------------------------------------------
1559 int start_firewall(void)
1561 DIR *dir;
1562 struct dirent *dirent;
1563 char s[256];
1564 char *c, *wanface;
1565 int n;
1566 int wanproto;
1567 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
1568 #ifdef TCONFIG_IPV6
1569 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
1570 #endif
1572 simple_lock("firewall");
1573 simple_lock("restrictions");
1575 wanproto = get_wan_proto();
1576 wanup = check_wanup();
1578 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1580 /* NAT performance tweaks
1581 * These values can be overriden later if needed via firewall script
1583 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1584 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1585 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1586 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1587 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1588 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1589 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1590 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1591 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1592 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1593 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1594 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1596 /* DoS-related tweaks */
1597 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1598 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1599 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1601 wanproto = get_wan_proto();
1602 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto == WP_DISABLED || wanproto == WP_STATIC) ? "0" : "1", 0, 0);
1604 #ifdef TCONFIG_EMF
1605 /* Force IGMPv2 due EMF limitations */
1606 if (nvram_get_int("emf_enable")) {
1607 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1608 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1610 #endif
1612 n = nvram_get_int("log_in");
1613 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1614 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1616 n = nvram_get_int("log_out");
1617 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1618 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1619 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1621 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1623 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1624 #ifdef TCONFIG_VLAN
1625 strlcpy(lan1face, nvram_safe_get("lan1_ifname"), IFNAMSIZ);
1626 strlcpy(lan2face, nvram_safe_get("lan2_ifname"), IFNAMSIZ);
1627 strlcpy(lan3face, nvram_safe_get("lan3_ifname"), IFNAMSIZ);
1628 #endif
1630 memcpy(&wanfaces, get_wanfaces(), sizeof(wanfaces));
1631 wanface = wanfaces.iface[0].name;
1632 #ifdef TCONFIG_IPV6
1633 strlcpy(wan6face, get_wan6face(), sizeof(wan6face));
1634 #endif
1636 #ifdef LINUX26
1637 can_enable_fastnat = 1;
1638 #endif
1640 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1641 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1642 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1643 #ifdef TCONFIG_VLAN
1645 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1646 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1647 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1649 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1650 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1651 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1653 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1654 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1655 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1657 #endif
1660 block obviously spoofed IP addresses
1662 rp_filter - BOOLEAN
1663 1 - do source validation by reversed path, as specified in RFC1812
1664 Recommended option for single homed hosts and stub network
1665 routers. Could cause troubles for complicated (not loop free)
1666 networks running a slow unreliable protocol (sort of RIP),
1667 or using static routes.
1668 0 - No source validation.
1670 c = nvram_get("wan_ifname");
1671 /* mcast needs rp filter to be turned off only for non default iface */
1672 if (!(nvram_match("multicast_pass", "1")) || !(nvram_match("udpxy_enable", "1")) || strcmp(wanface, c) == 0) c = NULL;
1674 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1675 while ((dirent = readdir(dir)) != NULL) {
1676 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
1677 f_write_string(s, (c && strcmp(dirent->d_name, c) == 0) ? "0" : "1", 0, 0);
1679 closedir(dir);
1682 remotemanage = 0;
1683 gateway_mode = !nvram_match("wk_mode", "router");
1684 if (gateway_mode) {
1685 /* Remote management */
1686 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1687 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1690 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1691 notice_set("iptables", "Unable to create iptables restore file");
1692 simple_unlock("firewall");
1693 return 0;
1696 #ifdef TCONFIG_IPV6
1697 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1698 notice_set("ip6tables", "Unable to create ip6tables restore file");
1699 simple_unlock("firewall");
1700 return 0;
1702 modprobe("nf_conntrack_ipv6");
1703 modprobe("ip6t_REJECT");
1704 #endif
1705 /*Start xt_IMQ and imq */
1706 modprobe("imq");
1707 #ifdef LINUX26
1708 modprobe("xt_IMQ");
1709 #else
1710 modprobe("ipt_IMQ");
1711 #endif
1713 mangle_table();
1714 nat_table();
1715 filter_table();
1717 fclose(ipt_file);
1718 ipt_file = NULL;
1720 #ifdef TCONFIG_IPV6
1721 fclose(ip6t_file);
1722 ip6t_file = NULL;
1723 #endif
1725 #ifdef DEBUG_IPTFILE
1726 if (debug_only) {
1727 simple_unlock("firewall");
1728 simple_unlock("restrictions");
1729 return 0;
1731 #endif
1733 save_webmon();
1735 if (nvram_get_int("upnp_enable") & 3) {
1736 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1737 if (killall("miniupnpd", SIGUSR2) == 0) {
1738 f_wait_notexists("/etc/upnp/save", 5);
1742 notice_set("iptables", "");
1743 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1744 led(LED_DIAG, 0);
1745 notice_set("iptables", "");
1747 else {
1748 sprintf(s, "%s.error", ipt_fname);
1749 rename(ipt_fname, s);
1750 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1751 led(LED_DIAG, 1);
1755 -P INPUT DROP
1756 -F INPUT
1757 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1758 -A INPUT -i br0 -j ACCEPT
1760 -P FORWARD DROP
1761 -F FORWARD
1762 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1763 -A FORWARD -i br0 -j ACCEPT
1768 #ifdef TCONFIG_IPV6
1769 if (ipv6_enabled()) {
1770 notice_set("ip6tables", "");
1771 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1772 notice_set("ip6tables", "");
1774 else {
1775 sprintf(s, "%s.error", ip6t_fname);
1776 rename(ip6t_fname, s);
1777 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1778 led(LED_DIAG, 1);
1781 else {
1782 eval("ip6tables", "-F");
1783 eval("ip6tables", "-t", "mangle", "-F");
1785 #endif
1787 if (nvram_get_int("upnp_enable") & 3) {
1788 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1789 killall("miniupnpd", SIGUSR2);
1792 simple_unlock("restrictions");
1793 sched_restrictions();
1794 enable_ip_forward();
1796 led(LED_DMZ, dmz_dst(NULL));
1798 #ifdef TCONFIG_IPV6
1799 modprobe_r("nf_conntrack_ipv6");
1800 modprobe_r("ip6t_LOG");
1801 modprobe_r("ip6t_REJECT");
1802 #endif
1803 #ifdef LINUX26
1804 modprobe_r("xt_layer7");
1805 modprobe_r("xt_recent");
1806 modprobe_r("xt_HL");
1807 modprobe_r("xt_length");
1808 modprobe_r("xt_web");
1809 modprobe_r("xt_webmon");
1810 modprobe_r("xt_dscp");
1811 #else
1812 modprobe_r("ipt_layer7");
1813 modprobe_r("ipt_recent");
1814 modprobe_r("ipt_TTL");
1815 modprobe_r("ipt_web");
1816 modprobe_r("ipt_webmon");
1817 modprobe_r("ipt_dscp");
1818 #endif
1819 modprobe_r("ipt_ipp2p");
1821 unlink("/var/webmon/domain");
1822 unlink("/var/webmon/search");
1824 #ifdef TCONFIG_OPENVPN
1825 run_vpn_firewall_scripts();
1826 #endif
1827 run_nvscript("script_fire", NULL, 1);
1829 start_arpbind();
1831 #ifdef LINUX26
1832 allow_fastnat("firewall", can_enable_fastnat);
1833 try_enabling_fastnat();
1834 #endif
1836 simple_unlock("firewall");
1837 return 0;
1840 int stop_firewall(void)
1842 led(LED_DMZ, 0);
1843 return 0;
1846 #ifdef DEBUG_IPTFILE
1847 void create_test_iptfile(void)
1849 debug_only = 1;
1850 start_firewall();
1851 debug_only = 0;
1853 #endif