Add SNMP configuration options for custom port and remote access
[tomato.git] / release / src / router / rc / firewall.c
blob05e28acdc27d188cc2c027ef64b81ac48724b0b5
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 #endif
155 // -----------------------------------------------------------------------------
158 static int ip2cclass(char *ipaddr, char *new, int count)
160 int ip[4];
162 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
163 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
168 static int dmz_dst(char *s)
170 struct in_addr ia;
171 char *p;
172 int n;
174 if (nvram_get_int("dmz_enable") <= 0) return 0;
176 p = nvram_safe_get("dmz_ipaddr");
177 if ((ia.s_addr = inet_addr(p)) == (in_addr_t)-1) {
178 if (((n = atoi(p)) <= 0) || (n >= 255)) return 0;
179 if (s) sprintf(s, "%s%d", lan_cclass, n);
180 return 1;
183 if (s) strcpy(s, inet_ntoa(ia));
184 return 1;
187 void ipt_log_unresolved(const char *addr, const char *addrtype, const char *categ, const char *name)
189 char *pre, *post;
191 pre = (name && *name) ? " for \"" : "";
192 post = (name && *name) ? "\"" : "";
194 syslog(LOG_WARNING, "firewall: "
195 "%s: not using %s%s%s%s (could not resolve as valid %s address)",
196 categ, addr, pre, (name) ? : "", post, (addrtype) ? : "IP");
199 int ipt_addr(char *addr, int maxlen, const char *s, const char *dir, int af,
200 int strict, const char *categ, const char *name)
202 char p[INET6_ADDRSTRLEN * 2];
203 int r = 0;
205 if ((s) && (*s) && (*dir))
207 if (sscanf(s, "%[0-9.]-%[0-9.]", p, p) == 2) {
208 snprintf(addr, maxlen, "-m iprange --%s-range %s", dir, s);
209 r = IPT_V4;
211 #ifdef TCONFIG_IPV6
212 else if (sscanf(s, "%[0-9A-Fa-f:]-%[0-9A-Fa-f:]", p, p) == 2) {
213 snprintf(addr, maxlen, "-m iprange --%s-range %s", dir, s);
214 r = IPT_V6;
216 #endif
217 else {
218 snprintf(addr, maxlen, "-%c %s", dir[0], s);
219 if (sscanf(s, "%[^/]/", p)) {
220 #ifdef TCONFIG_IPV6
221 r = host_addrtypes(p, strict ? af : (IPT_V4 | IPT_V6));
222 #else
223 r = host_addrtypes(p, IPT_V4);
224 #endif
228 else
230 *addr = 0;
231 r = (IPT_V4 | IPT_V6);
234 if ((r == 0 || (strict && ((r & af) != af))) && (categ && *categ)) {
235 ipt_log_unresolved(s, categ, name,
236 (af & IPT_V4 & ~r) ? "IPv4" : ((af & IPT_V6 & ~r) ? "IPv6" : NULL));
239 return (r & af);
242 #define ipt_source_strict(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 1, categ, name)
243 #define ipt_source(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 0, categ, name)
244 #define ip6t_source(s, src, categ, name) ipt_addr(src, 128, s, "src", IPT_V6, 0, categ, name)
247 static void get_src(const char *nv, char *src)
249 char *p;
251 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
252 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
254 else {
255 *src = 0;
260 void ipt_write(const char *format, ...)
262 va_list args;
264 va_start(args, format);
265 vfprintf(ipt_file, format, args);
266 va_end(args);
269 void ip6t_write(const char *format, ...)
271 #ifdef TCONFIG_IPV6
272 va_list args;
274 va_start(args, format);
275 vfprintf(ip6t_file, format, args);
276 va_end(args);
277 #endif
280 // -----------------------------------------------------------------------------
282 int ipt_dscp(const char *v, char *opt)
284 unsigned int n;
286 if (*v == 0) {
287 *opt = 0;
288 return 0;
291 n = strtoul(v, NULL, 0);
292 if (n > 63) n = 63;
293 sprintf(opt, " -m dscp --dscp 0x%02X", n);
295 #ifdef LINUX26
296 modprobe("xt_dscp");
297 #else
298 modprobe("ipt_dscp");
299 #endif
300 return 1;
303 // -----------------------------------------------------------------------------
306 int ipt_ipp2p(const char *v, char *opt)
308 int n = atoi(v);
310 if (n == 0) {
311 *opt = 0;
312 return 0;
315 strcpy(opt, "-m ipp2p ");
316 if ((n & 0xFFF) == 0xFFF) {
317 strcat(opt, "--ipp2p");
319 else {
320 // x12
321 if (n & 0x0001) strcat(opt, "--apple ");
322 if (n & 0x0002) strcat(opt, "--ares ");
323 if (n & 0x0004) strcat(opt, "--bit ");
324 if (n & 0x0008) strcat(opt, "--dc ");
325 if (n & 0x0010) strcat(opt, "--edk ");
326 if (n & 0x0020) strcat(opt, "--gnu ");
327 if (n & 0x0040) strcat(opt, "--kazaa ");
328 if (n & 0x0080) strcat(opt, "--mute ");
329 if (n & 0x0100) strcat(opt, "--soul ");
330 if (n & 0x0200) strcat(opt, "--waste ");
331 if (n & 0x0400) strcat(opt, "--winmx ");
332 if (n & 0x0800) strcat(opt, "--xdcc ");
335 modprobe("ipt_ipp2p");
336 return 1;
340 // -----------------------------------------------------------------------------
343 char **layer7_in;
345 // This L7 matches inbound traffic, caches the results, then the L7 outbound
346 // should read the cached result and set the appropriate marks -- zzz
347 void ipt_layer7_inbound(void)
349 int en, i;
350 char **p;
352 if (!layer7_in) return;
354 en = nvram_match("nf_l7in", "1");
355 if (en) {
356 ipt_write(":L7in - [0:0]\n");
357 for (i = 0; i < wanfaces.count; ++i) {
358 if (*(wanfaces.iface[i].name)) {
359 ipt_write("-A FORWARD -i %s -j L7in\n",
360 wanfaces.iface[i].name);
365 p = layer7_in;
366 while (*p) {
367 if (en) {
368 ipt_write("-A L7in %s -j RETURN\n", *p);
369 #ifdef LINUX26
370 can_enable_fastnat = 0;
371 #endif
373 free(*p);
374 ++p;
376 free(layer7_in);
377 layer7_in = NULL;
380 int ipt_layer7(const char *v, char *opt)
382 char s[128];
383 char *path;
385 *opt = 0;
386 if (*v == 0) return 0;
387 if (strlen(v) > 32) return -1;
389 path = "/etc/l7-extra";
390 sprintf(s, "%s/%s.pat", path, v);
391 if (!f_exists(s)) {
392 path = "/etc/l7-protocols";
393 sprintf(s, "%s/%s.pat", path, v);
394 if (!f_exists(s)) {
395 syslog(LOG_ERR, "L7 %s was not found", v);
396 return -1;
400 sprintf(opt, "-m layer7 --l7dir %s --l7proto %s", path, v);
402 if (nvram_match("nf_l7in", "1")) {
403 if (!layer7_in) layer7_in = calloc(51, sizeof(char *));
404 if (layer7_in) {
405 char **p;
407 p = layer7_in;
408 while (*p) {
409 if (strcmp(*p, opt) == 0) return 1;
410 ++p;
412 if (((p - layer7_in) / sizeof(char *)) < 50) *p = strdup(opt);
416 #ifdef LINUX26
417 modprobe("xt_layer7");
418 #else
419 modprobe("ipt_layer7");
420 #endif
421 return 1;
424 // -----------------------------------------------------------------------------
426 static void ipt_account(void) {
427 struct in_addr ipaddr, netmask, network;
428 char lanN_ifname[] = "lanXX_ifname";
429 char lanN_ipaddr[] = "lanXX_ipaddr";
430 char lanN_netmask[] = "lanXX_netmask";
431 char lanN[] = "lanXX";
432 char netaddrnetmask[] = "255.255.255.255/255.255.255.255 ";
433 char br;
435 for(br=0 ; br<=3 ; br++) {
436 char bridge[2] = "0";
437 if (br!=0)
438 bridge[0]+=br;
439 else
440 strcpy(bridge, "");
442 sprintf(lanN_ifname, "lan%s_ifname", bridge);
444 if (strcmp(nvram_safe_get(lanN_ifname), "")!=0) {
446 sprintf(lanN_ipaddr, "lan%s_ipaddr", bridge);
447 sprintf(lanN_netmask, "lan%s_netmask", bridge);
448 sprintf(lanN, "lan%s", bridge);
450 inet_aton(nvram_safe_get(lanN_ipaddr), &ipaddr);
451 inet_aton(nvram_safe_get(lanN_netmask), &netmask);
453 // bitwise AND of ip and netmask gives the network
454 network.s_addr = ipaddr.s_addr & netmask.s_addr;
456 sprintf(netaddrnetmask, "%s/%s", inet_ntoa(network), nvram_safe_get(lanN_netmask));
458 //ipv4 only
459 ipt_write("-A FORWARD -m account --aaddr %s --aname %s\n", netaddrnetmask, lanN);
464 // -----------------------------------------------------------------------------
466 static void save_webmon(void)
468 eval("cp", "/proc/webmon_recent_domains", "/var/webmon/domain");
469 eval("cp", "/proc/webmon_recent_searches", "/var/webmon/search");
472 static void ipt_webmon()
474 int wmtype, clear, i;
475 char t[512];
476 char src[128];
477 char *p, *c;
478 int ok;
480 if (!nvram_get_int("log_wm")) return;
482 #ifdef LINUX26
483 can_enable_fastnat = 0;
484 #endif
485 wmtype = nvram_get_int("log_wmtype");
486 clear = nvram_get_int("log_wmclear");
488 ip46t_write(":monitor - [0:0]\n");
490 // include IPs
491 strlcpy(t, wmtype == 1 ? nvram_safe_get("log_wmip") : "", sizeof(t));
492 p = t;
493 do {
494 if ((c = strchr(p, ',')) != NULL) *c = 0;
496 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
497 #ifdef TCONFIG_IPV6
498 if (*wan6face && (ok & IPT_V6))
499 ip6t_write("-A FORWARD -o %s %s -j monitor\n", wan6face, src);
500 #endif
501 if (ok & IPT_V4) {
502 for (i = 0; i < wanfaces.count; ++i) {
503 if (*(wanfaces.iface[i].name)) {
504 ipt_write("-A FORWARD -o %s %s -j monitor\n",
505 wanfaces.iface[i].name, src);
511 if (!c) break;
512 p = c + 1;
513 } while (*p);
515 // exclude IPs
516 if (wmtype == 2) {
517 strlcpy(t, nvram_safe_get("log_wmip"), sizeof(t));
518 p = t;
519 do {
520 if ((c = strchr(p, ',')) != NULL) *c = 0;
521 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
522 if (*src)
523 ip46t_flagged_write(ok, "-A monitor %s -j RETURN\n", src);
525 if (!c) break;
526 p = c + 1;
527 } while (*p);
530 ip46t_write(
531 "-A monitor -p tcp -m webmon "
532 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
533 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
534 (clear & 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
535 (clear & 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
537 #ifdef LINUX26
538 modprobe("xt_webmon");
539 #else
540 modprobe("ipt_webmon");
541 #endif
545 // -----------------------------------------------------------------------------
546 // MANGLE
547 // -----------------------------------------------------------------------------
549 static void mangle_table(void)
551 int ttl;
552 char *p, *wanface;
554 ip46t_write(
555 "*mangle\n"
556 ":PREROUTING ACCEPT [0:0]\n"
557 ":OUTPUT ACCEPT [0:0]\n");
559 if (wanup) {
561 ipt_qos();
562 //1 for mangle
563 ipt_qoslimit(1);
565 p = nvram_safe_get("nf_ttl");
566 if (strncmp(p, "c:", 2) == 0) {
567 p += 2;
568 ttl = atoi(p);
569 p = (ttl >= 0 && ttl <= 255) ? "set" : NULL;
571 else if ((ttl = atoi(p)) != 0) {
572 if (ttl > 0) {
573 p = "inc";
575 else {
576 ttl = -ttl;
577 p = "dec";
579 if (ttl > 255) p = NULL;
581 else p = NULL;
583 if (p) {
584 #ifdef LINUX26
585 modprobe("xt_HL");
586 #else
587 modprobe("ipt_TTL");
588 #endif
589 // set TTL on primary WAN iface only
590 wanface = wanfaces.iface[0].name;
591 ipt_write(
592 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
593 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
594 wanface, p, ttl,
595 wanface, p, ttl);
596 #ifdef TCONFIG_IPV6
597 // FIXME: IPv6 HL should be configurable separately from TTL.
598 // disable it until GUI setting is implemented.
599 #if 0
600 ip6t_write(
601 "-I PREROUTING -i %s -j HL --hl-%s %d\n"
602 "-I POSTROUTING -o %s -j HL --hl-%s %d\n",
603 wan6face, p, ttl,
604 wan6face, p, ttl);
605 #endif
606 #endif
610 ip46t_write("COMMIT\n");
613 // -----------------------------------------------------------------------------
614 // NAT
615 // -----------------------------------------------------------------------------
617 static void nat_table(void)
619 char lanaddr[32];
620 char lanmask[32];
621 #ifdef TCONFIG_VLAN
622 char lan1addr[32];
623 char lan1mask[32];
624 char lan2addr[32];
625 char lan2mask[32];
626 char lan3addr[32];
627 char lan3mask[32];
628 #endif
629 char dst[64];
630 char src[64];
631 char t[512];
632 char *p, *c;
633 int i;
635 ipt_write("*nat\n"
636 ":PREROUTING ACCEPT [0:0]\n"
637 ":POSTROUTING ACCEPT [0:0]\n"
638 ":OUTPUT ACCEPT [0:0]\n"
639 ":%s - [0:0]\n",
640 chain_wan_prerouting);
642 //2 for nat
643 ipt_qoslimit(2);
645 if (gateway_mode) {
646 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
647 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
648 #ifdef TCONFIG_VLAN
649 strlcpy(lan1addr, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr));
650 strlcpy(lan1mask, nvram_safe_get("lan1_netmask"), sizeof(lan1mask));
651 strlcpy(lan2addr, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr));
652 strlcpy(lan2mask, nvram_safe_get("lan2_netmask"), sizeof(lan2mask));
653 strlcpy(lan3addr, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr));
654 strlcpy(lan3mask, nvram_safe_get("lan3_netmask"), sizeof(lan3mask));
655 #endif
657 for (i = 0; i < wanfaces.count; ++i) {
658 if (*(wanfaces.iface[i].name)) {
659 // Drop incoming packets which destination IP address is to our LAN side directly
660 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
661 wanfaces.iface[i].name,
662 lanaddr, lanmask); // note: ipt will correct lanaddr
663 #ifdef TCONFIG_VLAN
664 if(strcmp(lan1addr,"")!=0)
665 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
666 wanfaces.iface[i].name,
667 lan1addr, lan1mask);
668 if(strcmp(lan2addr,"")!=0)
669 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
670 wanfaces.iface[i].name,
671 lan2addr, lan2mask);
672 if(strcmp(lan3addr,"")!=0)
673 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
674 wanfaces.iface[i].name,
675 lan3addr, lan3mask);
676 #endif
677 // chain_wan_prerouting
678 if (wanup) {
679 ipt_write("-A PREROUTING -d %s -j %s\n",
680 wanfaces.iface[i].ip, chain_wan_prerouting);
685 if (wanup) {
686 if (nvram_match("dns_intcpt", "1")) {
687 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
688 lanaddr, lanmask,
689 lanaddr, lanmask,
690 lanaddr);
691 #ifdef TCONFIG_VLAN
692 if(strcmp(lan1addr,"")!=0)
693 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
694 lan1addr, lan1mask,
695 lan1addr, lan1mask,
696 lan1addr);
697 if(strcmp(lan2addr,"")!=0)
698 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
699 lan2addr, lan2mask,
700 lan2addr, lan2mask,
701 lan2addr);
702 if(strcmp(lan3addr,"")!=0)
703 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
704 lan3addr, lan3mask,
705 lan3addr, lan3mask,
706 lan3addr);
707 #endif
710 // ICMP packets are always redirected to INPUT chains
711 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
713 ipt_forward(IPT_TABLE_NAT);
714 ipt_triggered(IPT_TABLE_NAT);
717 if (nvram_get_int("upnp_enable") & 3) {
718 ipt_write(":upnp - [0:0]\n");
720 for (i = 0; i < wanfaces.count; ++i) {
721 if (*(wanfaces.iface[i].name)) {
722 if (wanup) {
723 // ! for loopback (all) to work
724 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces.iface[i].ip);
726 else {
727 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces.iface[i].name);
733 if (wanup) {
734 if (dmz_dst(dst)) {
735 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
736 p = t;
737 do {
738 if ((c = strchr(p, ',')) != NULL) *c = 0;
739 if (ipt_source_strict(p, src, "dmz", NULL))
740 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
741 if (!c) break;
742 p = c + 1;
743 } while (*p);
747 p = "";
748 #ifdef TCONFIG_IPV6
749 switch (get_ipv6_service()) {
750 case IPV6_6IN4:
751 // avoid NATing proto-41 packets when using 6in4 tunnel
752 p = "-p ! 41";
753 break;
755 #endif
757 char *modem_ipaddr;
758 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
759 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
760 && (!foreach_wif(1, NULL, is_sta)) )
761 ipt_write("-A POSTROUTING -o %s -d %s -j MASQUERADE\n", nvram_safe_get("wan_ifname"), modem_ipaddr);
763 for (i = 0; i < wanfaces.count; ++i) {
764 if (*(wanfaces.iface[i].name)) {
765 if ((!wanup) || (nvram_get_int("ne_snat") != 1))
766 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p, wanfaces.iface[i].name);
767 else
768 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p, wanfaces.iface[i].name, wanfaces.iface[i].ip);
772 switch (nvram_get_int("nf_loopback")) {
773 case 1: // 1 = forwarded-only
774 case 2: // 2 = disable
775 break;
776 default: // 0 = all (same as block_loopback=0)
777 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
778 lanface,
779 lanaddr, lanmask,
780 lanaddr, lanmask,
781 lanaddr);
782 #ifdef TCONFIG_VLAN
783 if (strcmp(lan1face,"")!=0)
784 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
785 lan1face,
786 lan1addr, lan1mask,
787 lan1addr, lan1mask,
788 lan1addr);
789 if (strcmp(lan2face,"")!=0)
790 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
791 lan2face,
792 lan2addr, lan2mask,
793 lan2addr, lan2mask,
794 lan2addr);
795 if (strcmp(lan3face,"")!=0)
796 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
797 lan3face,
798 lan3addr, lan3mask,
799 lan3addr, lan3mask,
800 lan3addr);
801 #endif
802 break;
805 ipt_write("COMMIT\n");
808 // -----------------------------------------------------------------------------
809 // FILTER
810 // -----------------------------------------------------------------------------
812 static void filter_input(void)
814 char s[64];
815 char t[512];
816 char *en;
817 char *sec;
818 char *hit;
819 int n;
820 char *p, *c;
822 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
823 for (n = 0; n < wanfaces.count; ++n) {
824 if (*(wanfaces.iface[n].name)) {
825 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanfaces.iface[n].ip);
826 #ifdef TCONFIG_VLAN
827 if (strcmp(lan1face,"")!=0)
828 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face, wanfaces.iface[n].ip);
829 if (strcmp(lan2face,"")!=0)
830 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face, wanfaces.iface[n].ip);
831 if (strcmp(lan3face,"")!=0)
832 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face, wanfaces.iface[n].ip);
833 #endif
838 ipt_write(
839 "-A INPUT -m state --state INVALID -j DROP\n"
840 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
842 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
843 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
845 ? what if the user uses the start button in GUI ?
846 if (nvram_get_int("telnetd_eas"))
847 if (nvram_get_int("sshd_eas"))
849 #ifdef LINUX26
850 modprobe("xt_recent");
851 #else
852 modprobe("ipt_recent");
853 #endif
855 ipt_write(
856 "-N shlimit\n"
857 "-A shlimit -m recent --set --name shlimit\n"
858 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
859 atoi(hit) + 1, sec, chain_in_drop);
861 if (n & 1) {
862 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
863 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
864 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
867 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
870 #ifdef TCONFIG_FTP
871 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
872 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
873 #ifdef LINUX26
874 modprobe("xt_recent");
875 #else
876 modprobe("ipt_recent");
877 #endif
879 ipt_write(
880 "-N ftplimit\n"
881 "-A ftplimit -m recent --set --name ftp\n"
882 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
883 atoi(hit) + 1, sec, chain_in_drop);
884 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
886 #endif
888 ipt_write(
889 "-A INPUT -i lo -j ACCEPT\n"
890 "-A INPUT -i %s -j ACCEPT\n",
891 lanface);
892 #ifdef TCONFIG_VLAN
893 if (strcmp(lan1face,"")!=0)
894 ipt_write(
895 "-A INPUT -i %s -j ACCEPT\n",
896 lan1face);
897 if (strcmp(lan2face,"")!=0)
898 ipt_write(
899 "-A INPUT -i %s -j ACCEPT\n",
900 lan2face);
901 if (strcmp(lan3face,"")!=0)
902 ipt_write(
903 "-A INPUT -i %s -j ACCEPT\n",
904 lan3face);
905 #endif
907 #ifdef TCONFIG_IPV6
908 n = get_ipv6_service();
909 switch (n) {
910 case IPV6_ANYCAST_6TO4:
911 case IPV6_6IN4:
912 // Accept ICMP requests from the remote tunnel endpoint
913 if (n == IPV6_ANYCAST_6TO4)
914 sprintf(s, "192.88.99.%d", nvram_get_int("ipv6_relay"));
915 else
916 strlcpy(s, nvram_safe_get("ipv6_tun_v4end"), sizeof(s));
917 if (*s && strcmp(s, "0.0.0.0") != 0)
918 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s, chain_in_accept);
919 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept);
920 break;
922 #endif
924 // ICMP request from WAN interface
925 if (nvram_match("block_wan", "0")) {
926 if (nvram_match("block_wan_limit", "0")) {
927 // allow ICMP packets to be received
928 ipt_write("-A INPUT -p icmp -j %s\n", chain_in_accept);
929 // allow udp traceroute packets
930 ipt_write("-A INPUT -p udp --dport 33434:33534 -j %s\n", chain_in_accept);
931 } else {
932 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
933 ipt_write("-A INPUT -p icmp -m limit --limit %d/second -j %s\n", nvram_get_int("block_wan_limit_icmp"), chain_in_accept);
934 // allow udp traceroute packets, but restrict the flow to avoid ping flood attacks
935 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);
939 /* Accept incoming packets from broken dhcp servers, which are sending replies
940 * from addresses other than used for query. This could lead to a lower level
941 * of security, so allow to disable it via nvram variable.
943 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
944 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
947 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
948 p = t;
949 do {
950 if ((c = strchr(p, ',')) != NULL) *c = 0;
952 if (ipt_source(p, s, "remote management", NULL)) {
954 if (remotemanage) {
955 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
956 s, nvram_safe_get("http_wanport"), chain_in_accept);
959 if (nvram_get_int("sshd_remote")) {
960 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
961 s, nvram_safe_get("sshd_rport"), chain_in_accept);
965 if (!c) break;
966 p = c + 1;
967 } while (*p);
969 #ifdef TCONFIG_FTP // !!TB - FTP Server
970 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
971 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
972 p = t;
973 do {
974 if ((c = strchr(p, ',')) != NULL) *c = 0;
975 if (ipt_source(p, s, "ftp", "remote access")) {
976 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
977 s, nvram_safe_get("ftp_port"), chain_in_accept);
979 if (!c) break;
980 p = c + 1;
981 } while (*p);
983 #endif
985 #ifdef TCONFIG_SNMP
986 if( nvram_match( "snmp_enable", "1" ) && nvram_match("snmp_remote", "1"))
988 strlcpy(t, nvram_safe_get("snmp_remote_sip"), sizeof(t));
989 p = t;
990 do {
991 if ((c = strchr(p, ',')) != NULL) *c = 0;
993 if (ipt_source(p, s, "snmp", "remote")) {
994 ipt_write("-A INPUT -p udp %s --dport %s -j %s\n",
995 s, nvram_safe_get("snmp_port"), chain_in_accept);
998 if (!c) break;
999 p = c + 1;
1000 } while (*p);
1002 #endif
1004 // IGMP query from WAN interface
1005 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1006 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
1007 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
1010 // Routing protocol, RIP, accept
1011 if (nvram_invmatch("dr_wan_rx", "0")) {
1012 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
1015 // if logging
1016 if (*chain_in_drop == 'l') {
1017 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
1020 // default policy: DROP
1023 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
1024 static void clampmss(void)
1026 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1027 #ifdef TCONFIG_IPV6
1028 switch (get_ipv6_service()) {
1029 case IPV6_ANYCAST_6TO4:
1030 case IPV6_6IN4:
1031 ip6t_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1032 break;
1034 #endif
1037 static void filter_forward(void)
1039 char dst[64];
1040 char src[64];
1041 char t[512];
1042 char *p, *c;
1043 int i;
1045 if (nvram_match("cstats_enable", "1")) {
1046 ipt_account();
1049 #ifdef TCONFIG_IPV6
1050 ip6t_write(
1051 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
1052 #endif
1054 ip46t_write(
1055 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
1056 lanface, lanface);
1057 #ifdef TCONFIG_VLAN
1058 if (strcmp(lan1face,"")!=0)
1059 ip46t_write(
1060 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1061 lan1face, lan1face);
1062 if (strcmp(lan2face,"")!=0)
1063 ip46t_write(
1064 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1065 lan2face, lan2face);
1066 if (strcmp(lan3face,"")!=0)
1067 ip46t_write(
1068 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1069 lan3face, lan3face);
1071 char lanAccess[17] = "0000000000000000";
1072 const char *d, *sbr, *saddr, *dbr, *daddr, *desc;
1073 char *nv, *nvp, *b;
1074 int n;
1075 nvp = nv = strdup(nvram_safe_get("lan_access"));
1076 if (nv) {
1077 while ((b = strsep(&nvp, ">")) != NULL) {
1079 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
1081 1 = enabled
1082 0 = src bridge
1083 1.2.3.4 = src addr
1084 1 = dst bridge
1085 5.6.7.8 = dst addr
1086 desc = desc
1088 n = vstrsep(b, "<", &d, &sbr, &saddr, &dbr, &daddr, &desc);
1089 if (*d != '1')
1090 continue;
1091 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4|IPT_V6, 0, "LAN access", desc))
1092 continue;
1093 if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V4|IPT_V6, 0, "LAN access", desc))
1094 continue;
1096 //ipv4 only
1097 ipt_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
1098 "br",
1099 sbr,
1100 "br",
1101 dbr,
1102 src,
1103 dst);
1105 if ((strcmp(src,"")==0) && (strcmp(dst,"")==0))
1106 lanAccess[((*sbr-48)+(*dbr-48)*4)] = '1';
1110 free(nv);
1111 #endif
1113 ip46t_write(
1114 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
1116 // clamp tcp mss to pmtu
1117 clampmss();
1119 if (wanup) {
1120 ipt_restrictions();
1122 ipt_layer7_inbound();
1125 ipt_webmon();
1127 ip46t_write(
1128 ":wanin - [0:0]\n"
1129 ":wanout - [0:0]\n"
1130 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1132 #ifdef TCONFIG_VLAN
1133 char lanN_ifname[] = "lanXX_ifname";
1134 char br;
1135 for(br=0 ; br<=3 ; br++) {
1136 char bridge[2] = "0";
1137 if (br!=0)
1138 bridge[0]+=br;
1139 else
1140 strcpy(bridge, "");
1142 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1143 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1144 char lanN_ifname2[] = "lanXX_ifname";
1145 char br2;
1146 for(br2=0 ; br2<=3 ; br2++) {
1147 if (br==br2) continue;
1149 if (lanAccess[((br)+(br2)*4)] == '1') continue;
1151 char bridge2[2] = "0";
1152 if (br2!=0)
1153 bridge2[0]+=br2;
1154 else
1155 strcpy(bridge2, "");
1157 sprintf(lanN_ifname2, "lan%s_ifname", bridge2);
1158 if (strncmp(nvram_safe_get(lanN_ifname2), "br", 2) == 0) {
1159 ip46t_write("-A FORWARD -i %s -o %s -j DROP\n",
1160 nvram_safe_get(lanN_ifname),
1161 nvram_safe_get(lanN_ifname2));
1164 // ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1167 #endif
1169 #ifdef TCONFIG_PPTPD
1170 //Add for pptp server
1171 if (nvram_match("pptpd_enable", "1")) {
1172 ipt_write("-A INPUT -p tcp --dport 1723 -j ACCEPT\n");
1173 ipt_write("-A INPUT -p 47 -j ACCEPT\n");
1175 #endif
1177 #ifdef TCONFIG_IPV6
1178 // Filter out invalid WAN->WAN connections
1179 if (*wan6face)
1180 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face, lanface, chain_in_drop);
1182 #ifdef LINUX26
1183 modprobe("xt_length");
1184 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1185 #endif
1187 // ICMPv6 rules
1188 for (i = 0; i < sizeof(allowed_icmpv6)/sizeof(int); ++i) {
1189 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[i], chain_in_accept);
1192 if (*wan6face) {
1193 ip6t_write(
1194 "-A FORWARD -i %s -j wanin\n" // generic from wan
1195 "-A FORWARD -o %s -j wanout\n", // generic to wan
1196 wan6face, wan6face);
1198 #endif
1200 for (i = 0; i < wanfaces.count; ++i) {
1201 if (*(wanfaces.iface[i].name)) {
1202 ipt_write(
1203 "-A FORWARD -i %s -j wanin\n" // generic from wan
1204 "-A FORWARD -o %s -j wanout\n", // generic to wan
1205 wanfaces.iface[i].name, wanfaces.iface[i].name);
1209 #ifdef TCONFIG_VLAN
1210 for(br=0 ; br<=3 ; br++) {
1211 char bridge[2] = "0";
1212 if (br!=0)
1213 bridge[0]+=br;
1214 else
1215 strcpy(bridge, "");
1217 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1218 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1219 ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1222 #else
1223 ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1224 #endif
1226 // #ifdef TCONFIG_VLAN
1227 /* for (i = 0; i < wanfaces.count; ++i) {
1228 if (*(wanfaces.iface[i].name)) {
1229 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wanfaces.iface[i].name, chain_out_accept);
1230 if (strcmp(lan1face,"")!=0)
1231 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wanfaces.iface[i].name, chain_out_accept);
1232 if (strcmp(lan2face,"")!=0)
1233 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wanfaces.iface[i].name, chain_out_accept);
1234 if (strcmp(lan3face,"")!=0)
1235 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wanfaces.iface[i].name, chain_out_accept);
1239 // #else
1240 // ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1241 // #endif
1243 #ifdef TCONFIG_IPV6
1244 //IPv6 forward LAN->WAN accept
1245 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wan6face, chain_out_accept);
1246 #ifdef TCONFIG_VLAN
1247 if (strcmp(lan1face,"")!=0)
1248 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wan6face, chain_out_accept);
1249 if (strcmp(lan2face,"")!=0)
1250 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wan6face, chain_out_accept);
1251 if (strcmp(lan3face,"")!=0)
1252 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wan6face, chain_out_accept);
1253 #endif
1254 #endif
1256 if (nvram_get_int("upnp_enable") & 3) {
1257 ipt_write(":upnp - [0:0]\n");
1258 for (i = 0; i < wanfaces.count; ++i) {
1259 if (*(wanfaces.iface[i].name)) {
1260 ipt_write("-A FORWARD -i %s -j upnp\n",
1261 wanfaces.iface[i].name);
1266 if (wanup) {
1267 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1268 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
1270 ipt_triggered(IPT_TABLE_FILTER);
1271 ipt_forward(IPT_TABLE_FILTER);
1272 #ifdef TCONFIG_IPV6
1273 ip6t_forward();
1274 #endif
1276 if (dmz_dst(dst)) {
1277 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
1278 p = t;
1279 do {
1280 if ((c = strchr(p, ',')) != NULL) *c = 0;
1281 if (ipt_source_strict(p, src, "dmz", NULL))
1282 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface, src, dst, chain_in_accept);
1283 if (!c) break;
1284 p = c + 1;
1285 } while (*p);
1289 // default policy: DROP
1292 static void filter_log(void)
1294 int n;
1295 char limit[128];
1297 n = nvram_get_int("log_limit");
1298 if ((n >= 1) && (n <= 9999)) {
1299 sprintf(limit, "-m limit --limit %d/m", n);
1301 else {
1302 limit[0] = 0;
1305 #ifdef TCONFIG_IPV6
1306 modprobe("ip6t_LOG");
1307 #endif
1308 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
1309 ip46t_write(
1310 ":logdrop - [0:0]\n"
1311 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1312 #ifdef LINUX26
1313 " --log-macdecode"
1314 #endif
1315 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1316 "-A logdrop -j DROP\n"
1317 ":logreject - [0:0]\n"
1318 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1319 #ifdef LINUX26
1320 " --log-macdecode"
1321 #endif
1322 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1323 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1324 limit, limit);
1326 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
1327 ip46t_write(
1328 ":logaccept - [0:0]\n"
1329 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1330 #ifdef LINUX26
1331 " --log-macdecode"
1332 #endif
1333 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1334 "-A logaccept -j ACCEPT\n",
1335 limit);
1339 #ifdef TCONFIG_IPV6
1340 static void filter6_input(void)
1342 char s[128];
1343 char t[512];
1344 char *en;
1345 char *sec;
1346 char *hit;
1347 int n;
1348 char *p, *c;
1350 // RFC-4890, sec. 4.4.1
1351 const int allowed_local_icmpv6[] =
1352 { 130, 131, 132, 133, 134, 135, 136,
1353 141, 142, 143,
1354 148, 149, 151, 152, 153 };
1356 ip6t_write(
1357 "-A INPUT -m rt --rt-type 0 -j %s\n"
1358 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1359 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1360 chain_in_drop);
1362 #ifdef LINUX26
1363 modprobe("xt_length");
1364 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1365 #endif
1367 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
1368 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
1369 #ifdef LINUX26
1370 modprobe("xt_recent");
1371 #else
1372 modprobe("ipt_recent");
1373 #endif
1375 ip6t_write(
1376 "-N shlimit\n"
1377 "-A shlimit -m recent --set --name shlimit\n"
1378 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1379 atoi(hit) + 1, sec, chain_in_drop);
1381 if (n & 1) {
1382 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
1383 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1384 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1387 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"));
1390 #ifdef TCONFIG_FTP
1391 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
1392 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
1393 #ifdef LINUX26
1394 modprobe("xt_recent");
1395 #else
1396 modprobe("ipt_recent");
1397 #endif
1399 ip6t_write(
1400 "-N ftplimit\n"
1401 "-A ftplimit -m recent --set --name ftp\n"
1402 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1403 atoi(hit) + 1, sec, chain_in_drop);
1404 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1406 #endif // TCONFIG_FTP
1408 ip6t_write(
1409 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1410 "-A INPUT -i lo -j ACCEPT\n",
1411 lanface );
1413 switch (get_ipv6_service()) {
1414 case IPV6_ANYCAST_6TO4:
1415 case IPV6_NATIVE_DHCP:
1416 // allow responses from the dhcpv6 server
1417 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept);
1418 break;
1421 // ICMPv6 rules
1422 const int allowed_icmpv6[6] = { 1, 2, 3, 4, 128, 129 };
1423 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
1424 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
1426 for (n = 0; n < sizeof(allowed_local_icmpv6)/sizeof(int); n++) {
1427 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6[n], chain_in_accept);
1430 // Remote Managment
1431 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1432 p = t;
1433 do {
1434 if ((c = strchr(p, ',')) != NULL) *c = 0;
1436 if (ip6t_source(p, s, "remote management", NULL)) {
1438 if (remotemanage) {
1439 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1440 s, nvram_safe_get("http_wanport"), chain_in_accept);
1443 if (nvram_get_int("sshd_remote")) {
1444 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1445 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1449 if (!c) break;
1450 p = c + 1;
1451 } while (*p);
1453 #ifdef TCONFIG_FTP
1454 // FTP server
1455 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1456 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1457 p = t;
1458 do {
1459 if ((c = strchr(p, ',')) != NULL) *c = 0;
1460 if (ip6t_source(p, s, "ftp", "remote access")) {
1461 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1462 s, nvram_safe_get("ftp_port"), chain_in_accept);
1464 if (!c) break;
1465 p = c + 1;
1466 } while (*p);
1468 #endif
1470 // if logging
1471 if (*chain_in_drop == 'l') {
1472 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
1475 // default policy: DROP
1478 #endif
1480 static void filter_table(void)
1482 ip46t_write(
1483 "*filter\n"
1484 ":INPUT DROP [0:0]\n"
1485 ":OUTPUT ACCEPT [0:0]\n"
1488 filter_log();
1490 filter_input();
1491 #ifdef TCONFIG_IPV6
1492 filter6_input();
1493 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop);
1494 #endif
1496 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
1497 ip46t_write(":FORWARD DROP [0:0]\n");
1498 filter_forward();
1500 else {
1501 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1502 clampmss();
1504 ip46t_write("COMMIT\n");
1507 // -----------------------------------------------------------------------------
1509 int start_firewall(void)
1511 DIR *dir;
1512 struct dirent *dirent;
1513 char s[256];
1514 char *c, *wanface;
1515 int n;
1516 int wanproto;
1517 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
1518 #ifdef TCONFIG_IPV6
1519 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
1520 #endif
1522 simple_lock("firewall");
1523 simple_lock("restrictions");
1525 wanproto = get_wan_proto();
1526 wanup = check_wanup();
1528 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1530 /* NAT performance tweaks
1531 * These values can be overriden later if needed via firewall script
1533 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1534 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1535 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1536 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1537 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1538 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1539 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1540 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1541 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1542 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1543 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1544 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1546 /* DoS-related tweaks */
1547 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1548 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1549 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1551 wanproto = get_wan_proto();
1552 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto == WP_DISABLED || wanproto == WP_STATIC) ? "0" : "1", 0, 0);
1554 #ifdef TCONFIG_EMF
1555 /* Force IGMPv2 due EMF limitations */
1556 if (nvram_get_int("emf_enable")) {
1557 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1558 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1560 #endif
1562 n = nvram_get_int("log_in");
1563 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1564 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1566 n = nvram_get_int("log_out");
1567 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1568 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1569 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1571 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1573 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1574 #ifdef TCONFIG_VLAN
1575 strlcpy(lan1face, nvram_safe_get("lan1_ifname"), IFNAMSIZ);
1576 strlcpy(lan2face, nvram_safe_get("lan2_ifname"), IFNAMSIZ);
1577 strlcpy(lan3face, nvram_safe_get("lan3_ifname"), IFNAMSIZ);
1578 #endif
1580 memcpy(&wanfaces, get_wanfaces(), sizeof(wanfaces));
1581 wanface = wanfaces.iface[0].name;
1582 #ifdef TCONFIG_IPV6
1583 strlcpy(wan6face, get_wan6face(), sizeof(wan6face));
1584 #endif
1586 #ifdef LINUX26
1587 can_enable_fastnat = 1;
1588 #endif
1590 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1591 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1592 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1593 #ifdef TCONFIG_VLAN
1595 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1596 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1597 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1599 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1600 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1601 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1603 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1604 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1605 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1607 #endif
1610 block obviously spoofed IP addresses
1612 rp_filter - BOOLEAN
1613 1 - do source validation by reversed path, as specified in RFC1812
1614 Recommended option for single homed hosts and stub network
1615 routers. Could cause troubles for complicated (not loop free)
1616 networks running a slow unreliable protocol (sort of RIP),
1617 or using static routes.
1618 0 - No source validation.
1620 c = nvram_get("wan_ifname");
1621 /* mcast needs rp filter to be turned off only for non default iface */
1622 if (!(nvram_match("multicast_pass", "1")) || !(nvram_match("udpxy_enable", "1")) || strcmp(wanface, c) == 0) c = NULL;
1624 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1625 while ((dirent = readdir(dir)) != NULL) {
1626 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
1627 f_write_string(s, (c && strcmp(dirent->d_name, c) == 0) ? "0" : "1", 0, 0);
1629 closedir(dir);
1632 remotemanage = 0;
1633 gateway_mode = !nvram_match("wk_mode", "router");
1634 if (gateway_mode) {
1635 /* Remote management */
1636 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1637 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1640 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1641 notice_set("iptables", "Unable to create iptables restore file");
1642 simple_unlock("firewall");
1643 return 0;
1646 #ifdef TCONFIG_IPV6
1647 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1648 notice_set("ip6tables", "Unable to create ip6tables restore file");
1649 simple_unlock("firewall");
1650 return 0;
1652 modprobe("nf_conntrack_ipv6");
1653 modprobe("ip6t_REJECT");
1654 #endif
1655 /*Start xt_IMQ and imq */
1656 modprobe("imq");
1657 #ifdef LINUX26
1658 modprobe("xt_IMQ");
1659 #else
1660 modprobe("ipt_IMQ");
1661 #endif
1663 mangle_table();
1664 nat_table();
1665 filter_table();
1667 fclose(ipt_file);
1668 ipt_file = NULL;
1670 #ifdef TCONFIG_IPV6
1671 fclose(ip6t_file);
1672 ip6t_file = NULL;
1673 #endif
1675 #ifdef DEBUG_IPTFILE
1676 if (debug_only) {
1677 simple_unlock("firewall");
1678 simple_unlock("restrictions");
1679 return 0;
1681 #endif
1683 save_webmon();
1685 if (nvram_get_int("upnp_enable") & 3) {
1686 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1687 if (killall("miniupnpd", SIGUSR2) == 0) {
1688 f_wait_notexists("/etc/upnp/save", 5);
1692 notice_set("iptables", "");
1693 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1694 led(LED_DIAG, 0);
1695 notice_set("iptables", "");
1697 else {
1698 sprintf(s, "%s.error", ipt_fname);
1699 rename(ipt_fname, s);
1700 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1701 led(LED_DIAG, 1);
1705 -P INPUT DROP
1706 -F INPUT
1707 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1708 -A INPUT -i br0 -j ACCEPT
1710 -P FORWARD DROP
1711 -F FORWARD
1712 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1713 -A FORWARD -i br0 -j ACCEPT
1718 #ifdef TCONFIG_IPV6
1719 if (ipv6_enabled()) {
1720 notice_set("ip6tables", "");
1721 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1722 notice_set("ip6tables", "");
1724 else {
1725 sprintf(s, "%s.error", ip6t_fname);
1726 rename(ip6t_fname, s);
1727 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1728 led(LED_DIAG, 1);
1731 else {
1732 eval("ip6tables", "-F");
1733 eval("ip6tables", "-t", "mangle", "-F");
1735 #endif
1737 if (nvram_get_int("upnp_enable") & 3) {
1738 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1739 killall("miniupnpd", SIGUSR2);
1742 simple_unlock("restrictions");
1743 sched_restrictions();
1744 enable_ip_forward();
1746 led(LED_DMZ, dmz_dst(NULL));
1748 #ifdef TCONFIG_IPV6
1749 modprobe_r("nf_conntrack_ipv6");
1750 modprobe_r("ip6t_LOG");
1751 modprobe_r("ip6t_REJECT");
1752 #endif
1753 #ifdef LINUX26
1754 modprobe_r("xt_layer7");
1755 modprobe_r("xt_recent");
1756 modprobe_r("xt_HL");
1757 modprobe_r("xt_length");
1758 modprobe_r("xt_web");
1759 modprobe_r("xt_webmon");
1760 modprobe_r("xt_dscp");
1761 #else
1762 modprobe_r("ipt_layer7");
1763 modprobe_r("ipt_recent");
1764 modprobe_r("ipt_TTL");
1765 modprobe_r("ipt_web");
1766 modprobe_r("ipt_webmon");
1767 modprobe_r("ipt_dscp");
1768 #endif
1769 modprobe_r("ipt_ipp2p");
1771 unlink("/var/webmon/domain");
1772 unlink("/var/webmon/search");
1774 #ifdef TCONFIG_OPENVPN
1775 run_vpn_firewall_scripts();
1776 #endif
1777 run_nvscript("script_fire", NULL, 1);
1779 start_arpbind();
1781 #ifdef LINUX26
1782 allow_fastnat("firewall", can_enable_fastnat);
1783 try_enabling_fastnat();
1784 #endif
1786 simple_unlock("firewall");
1787 return 0;
1790 int stop_firewall(void)
1792 led(LED_DMZ, 0);
1793 return 0;
1796 #ifdef DEBUG_IPTFILE
1797 void create_test_iptfile(void)
1799 debug_only = 1;
1800 start_firewall();
1801 debug_only = 0;
1803 #endif