fix duplicated ipt_account();
[tomato.git] / release / src / router / rc / firewall.c
blobba19d5310619ce1544839920ff308738dfa0d396
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 ipt_write("-A FORWARD -m account --aaddr %s --aname %s\n", netaddrnetmask, lanN);
463 // -----------------------------------------------------------------------------
465 static void save_webmon(void)
467 eval("cp", "/proc/webmon_recent_domains", "/var/webmon/domain");
468 eval("cp", "/proc/webmon_recent_searches", "/var/webmon/search");
471 static void ipt_webmon()
473 int wmtype, clear, i;
474 char t[512];
475 char src[128];
476 char *p, *c;
477 int ok;
479 if (!nvram_get_int("log_wm")) return;
481 #ifdef LINUX26
482 can_enable_fastnat = 0;
483 #endif
484 wmtype = nvram_get_int("log_wmtype");
485 clear = nvram_get_int("log_wmclear");
487 ip46t_write(":monitor - [0:0]\n");
489 // include IPs
490 strlcpy(t, wmtype == 1 ? nvram_safe_get("log_wmip") : "", sizeof(t));
491 p = t;
492 do {
493 if ((c = strchr(p, ',')) != NULL) *c = 0;
495 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
496 #ifdef TCONFIG_IPV6
497 if (*wan6face && (ok & IPT_V6))
498 ip6t_write("-A FORWARD -o %s %s -j monitor\n", wan6face, src);
499 #endif
500 if (ok & IPT_V4) {
501 for (i = 0; i < wanfaces.count; ++i) {
502 if (*(wanfaces.iface[i].name)) {
503 ipt_write("-A FORWARD -o %s %s -j monitor\n",
504 wanfaces.iface[i].name, src);
510 if (!c) break;
511 p = c + 1;
512 } while (*p);
514 // exclude IPs
515 if (wmtype == 2) {
516 strlcpy(t, nvram_safe_get("log_wmip"), sizeof(t));
517 p = t;
518 do {
519 if ((c = strchr(p, ',')) != NULL) *c = 0;
520 if ((ok = ipt_addr(src, sizeof(src), p, "src", IPT_V4|IPT_V6, 0, "webmon", NULL))) {
521 if (*src)
522 ip46t_flagged_write(ok, "-A monitor %s -j RETURN\n", src);
524 if (!c) break;
525 p = c + 1;
526 } while (*p);
529 ip46t_write(
530 "-A monitor -p tcp -m webmon "
531 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
532 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
533 (clear & 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
534 (clear & 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
536 #ifdef LINUX26
537 modprobe("xt_webmon");
538 #else
539 modprobe("ipt_webmon");
540 #endif
544 // -----------------------------------------------------------------------------
545 // MANGLE
546 // -----------------------------------------------------------------------------
548 static void mangle_table(void)
550 int ttl;
551 char *p, *wanface;
553 ip46t_write(
554 "*mangle\n"
555 ":PREROUTING ACCEPT [0:0]\n"
556 ":OUTPUT ACCEPT [0:0]\n");
558 if (wanup) {
560 ipt_qos();
561 //1 for mangle
562 ipt_qoslimit(1);
564 p = nvram_safe_get("nf_ttl");
565 if (strncmp(p, "c:", 2) == 0) {
566 p += 2;
567 ttl = atoi(p);
568 p = (ttl >= 0 && ttl <= 255) ? "set" : NULL;
570 else if ((ttl = atoi(p)) != 0) {
571 if (ttl > 0) {
572 p = "inc";
574 else {
575 ttl = -ttl;
576 p = "dec";
578 if (ttl > 255) p = NULL;
580 else p = NULL;
582 if (p) {
583 #ifdef LINUX26
584 modprobe("xt_HL");
585 #else
586 modprobe("ipt_TTL");
587 #endif
588 // set TTL on primary WAN iface only
589 wanface = wanfaces.iface[0].name;
590 ipt_write(
591 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
592 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
593 wanface, p, ttl,
594 wanface, p, ttl);
595 #ifdef TCONFIG_IPV6
596 // FIXME: IPv6 HL should be configurable separately from TTL.
597 // disable it until GUI setting is implemented.
598 #if 0
599 ip6t_write(
600 "-I PREROUTING -i %s -j HL --hl-%s %d\n"
601 "-I POSTROUTING -o %s -j HL --hl-%s %d\n",
602 wan6face, p, ttl,
603 wan6face, p, ttl);
604 #endif
605 #endif
609 ip46t_write("COMMIT\n");
612 // -----------------------------------------------------------------------------
613 // NAT
614 // -----------------------------------------------------------------------------
616 static void nat_table(void)
618 char lanaddr[32];
619 char lanmask[32];
620 #ifdef TCONFIG_VLAN
621 char lan1addr[32];
622 char lan1mask[32];
623 char lan2addr[32];
624 char lan2mask[32];
625 char lan3addr[32];
626 char lan3mask[32];
627 #endif
628 char dst[64];
629 char src[64];
630 char t[512];
631 char *p, *c;
632 int i;
634 ipt_write("*nat\n"
635 ":PREROUTING ACCEPT [0:0]\n"
636 ":POSTROUTING ACCEPT [0:0]\n"
637 ":OUTPUT ACCEPT [0:0]\n"
638 ":%s - [0:0]\n",
639 chain_wan_prerouting);
641 //2 for nat
642 ipt_qoslimit(2);
644 if (gateway_mode) {
645 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
646 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
647 #ifdef TCONFIG_VLAN
648 strlcpy(lan1addr, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr));
649 strlcpy(lan1mask, nvram_safe_get("lan1_netmask"), sizeof(lan1mask));
650 strlcpy(lan2addr, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr));
651 strlcpy(lan2mask, nvram_safe_get("lan2_netmask"), sizeof(lan2mask));
652 strlcpy(lan3addr, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr));
653 strlcpy(lan3mask, nvram_safe_get("lan3_netmask"), sizeof(lan3mask));
654 #endif
656 for (i = 0; i < wanfaces.count; ++i) {
657 if (*(wanfaces.iface[i].name)) {
658 // Drop incoming packets which destination IP address is to our LAN side directly
659 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
660 wanfaces.iface[i].name,
661 lanaddr, lanmask); // note: ipt will correct lanaddr
662 #ifdef TCONFIG_VLAN
663 if(strcmp(lan1addr,"")!=0)
664 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
665 wanfaces.iface[i].name,
666 lan1addr, lan1mask);
667 if(strcmp(lan2addr,"")!=0)
668 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
669 wanfaces.iface[i].name,
670 lan2addr, lan2mask);
671 if(strcmp(lan3addr,"")!=0)
672 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
673 wanfaces.iface[i].name,
674 lan3addr, lan3mask);
675 #endif
676 // chain_wan_prerouting
677 if (wanup) {
678 ipt_write("-A PREROUTING -d %s -j %s\n",
679 wanfaces.iface[i].ip, chain_wan_prerouting);
684 if (wanup) {
685 if (nvram_match("dns_intcpt", "1")) {
686 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
687 lanaddr, lanmask,
688 lanaddr, lanmask,
689 lanaddr);
690 #ifdef TCONFIG_VLAN
691 if(strcmp(lan1addr,"")!=0)
692 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
693 lan1addr, lan1mask,
694 lan1addr, lan1mask,
695 lan1addr);
696 if(strcmp(lan2addr,"")!=0)
697 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
698 lan2addr, lan2mask,
699 lan2addr, lan2mask,
700 lan2addr);
701 if(strcmp(lan3addr,"")!=0)
702 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
703 lan3addr, lan3mask,
704 lan3addr, lan3mask,
705 lan3addr);
706 #endif
709 // ICMP packets are always redirected to INPUT chains
710 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
712 ipt_forward(IPT_TABLE_NAT);
713 ipt_triggered(IPT_TABLE_NAT);
716 if (nvram_get_int("upnp_enable") & 3) {
717 ipt_write(":upnp - [0:0]\n");
719 for (i = 0; i < wanfaces.count; ++i) {
720 if (*(wanfaces.iface[i].name)) {
721 if (wanup) {
722 // ! for loopback (all) to work
723 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces.iface[i].ip);
725 else {
726 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces.iface[i].name);
732 if (wanup) {
733 if (dmz_dst(dst)) {
734 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
735 p = t;
736 do {
737 if ((c = strchr(p, ',')) != NULL) *c = 0;
738 if (ipt_source_strict(p, src, "dmz", NULL))
739 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
740 if (!c) break;
741 p = c + 1;
742 } while (*p);
746 p = "";
747 #ifdef TCONFIG_IPV6
748 switch (get_ipv6_service()) {
749 case IPV6_6IN4:
750 // avoid NATing proto-41 packets when using 6in4 tunnel
751 p = "-p ! 41";
752 break;
754 #endif
756 char *modem_ipaddr;
757 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
758 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
759 && (!foreach_wif(1, NULL, is_sta)) )
760 ipt_write("-A POSTROUTING -o %s -d %s -j MASQUERADE\n", nvram_safe_get("wan_ifname"), modem_ipaddr);
762 for (i = 0; i < wanfaces.count; ++i) {
763 if (*(wanfaces.iface[i].name)) {
764 if ((!wanup) || (nvram_get_int("ne_snat") != 1))
765 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p, wanfaces.iface[i].name);
766 else
767 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p, wanfaces.iface[i].name, wanfaces.iface[i].ip);
771 switch (nvram_get_int("nf_loopback")) {
772 case 1: // 1 = forwarded-only
773 case 2: // 2 = disable
774 break;
775 default: // 0 = all (same as block_loopback=0)
776 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
777 lanface,
778 lanaddr, lanmask,
779 lanaddr, lanmask,
780 lanaddr);
781 #ifdef TCONFIG_VLAN
782 if (strcmp(lan1face,"")!=0)
783 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
784 lan1face,
785 lan1addr, lan1mask,
786 lan1addr, lan1mask,
787 lan1addr);
788 if (strcmp(lan2face,"")!=0)
789 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
790 lan2face,
791 lan2addr, lan2mask,
792 lan2addr, lan2mask,
793 lan2addr);
794 if (strcmp(lan3face,"")!=0)
795 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
796 lan3face,
797 lan3addr, lan3mask,
798 lan3addr, lan3mask,
799 lan3addr);
800 #endif
801 break;
804 ipt_write("COMMIT\n");
807 // -----------------------------------------------------------------------------
808 // FILTER
809 // -----------------------------------------------------------------------------
811 static void filter_input(void)
813 char s[64];
814 char t[512];
815 char *en;
816 char *sec;
817 char *hit;
818 int n;
819 char *p, *c;
821 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
822 for (n = 0; n < wanfaces.count; ++n) {
823 if (*(wanfaces.iface[n].name)) {
824 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanfaces.iface[n].ip);
825 #ifdef TCONFIG_VLAN
826 if (strcmp(lan1face,"")!=0)
827 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face, wanfaces.iface[n].ip);
828 if (strcmp(lan2face,"")!=0)
829 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face, wanfaces.iface[n].ip);
830 if (strcmp(lan3face,"")!=0)
831 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face, wanfaces.iface[n].ip);
832 #endif
837 ipt_write(
838 "-A INPUT -m state --state INVALID -j DROP\n"
839 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
841 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
842 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
844 ? what if the user uses the start button in GUI ?
845 if (nvram_get_int("telnetd_eas"))
846 if (nvram_get_int("sshd_eas"))
848 #ifdef LINUX26
849 modprobe("xt_recent");
850 #else
851 modprobe("ipt_recent");
852 #endif
854 ipt_write(
855 "-N shlimit\n"
856 "-A shlimit -m recent --set --name shlimit\n"
857 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
858 atoi(hit) + 1, sec, chain_in_drop);
860 if (n & 1) {
861 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
862 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
863 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
866 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
869 #ifdef TCONFIG_FTP
870 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
871 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
872 #ifdef LINUX26
873 modprobe("xt_recent");
874 #else
875 modprobe("ipt_recent");
876 #endif
878 ipt_write(
879 "-N ftplimit\n"
880 "-A ftplimit -m recent --set --name ftp\n"
881 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
882 atoi(hit) + 1, sec, chain_in_drop);
883 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
885 #endif
887 ipt_write(
888 "-A INPUT -i lo -j ACCEPT\n"
889 "-A INPUT -i %s -j ACCEPT\n",
890 lanface);
891 #ifdef TCONFIG_VLAN
892 if (strcmp(lan1face,"")!=0)
893 ipt_write(
894 "-A INPUT -i %s -j ACCEPT\n",
895 lan1face);
896 if (strcmp(lan2face,"")!=0)
897 ipt_write(
898 "-A INPUT -i %s -j ACCEPT\n",
899 lan2face);
900 if (strcmp(lan3face,"")!=0)
901 ipt_write(
902 "-A INPUT -i %s -j ACCEPT\n",
903 lan3face);
904 #endif
906 #ifdef TCONFIG_IPV6
907 n = get_ipv6_service();
908 switch (n) {
909 case IPV6_ANYCAST_6TO4:
910 case IPV6_6IN4:
911 // Accept ICMP requests from the remote tunnel endpoint
912 if (n == IPV6_ANYCAST_6TO4)
913 sprintf(s, "192.88.99.%d", nvram_get_int("ipv6_relay"));
914 else
915 strlcpy(s, nvram_safe_get("ipv6_tun_v4end"), sizeof(s));
916 if (*s && strcmp(s, "0.0.0.0") != 0)
917 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s, chain_in_accept);
918 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept);
919 break;
921 #endif
923 // ICMP request from WAN interface
924 if (nvram_match("block_wan", "0")) {
925 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
926 ipt_write("-A INPUT -p icmp -m limit --limit 1/second -j %s\n", chain_in_accept);
927 // allow udp traceroute packets
928 ipt_write("-A INPUT -p udp --dport 33434:33534 -m limit --limit 5/second -j %s\n", chain_in_accept);
931 /* Accept incoming packets from broken dhcp servers, which are sending replies
932 * from addresses other than used for query. This could lead to a lower level
933 * of security, so allow to disable it via nvram variable.
935 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
936 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
939 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
940 p = t;
941 do {
942 if ((c = strchr(p, ',')) != NULL) *c = 0;
944 if (ipt_source(p, s, "remote management", NULL)) {
946 if (remotemanage) {
947 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
948 s, nvram_safe_get("http_wanport"), chain_in_accept);
951 if (nvram_get_int("sshd_remote")) {
952 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
953 s, nvram_safe_get("sshd_rport"), chain_in_accept);
957 if (!c) break;
958 p = c + 1;
959 } while (*p);
961 #ifdef TCONFIG_FTP // !!TB - FTP Server
962 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
963 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
964 p = t;
965 do {
966 if ((c = strchr(p, ',')) != NULL) *c = 0;
967 if (ipt_source(p, s, "ftp", "remote access")) {
968 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
969 s, nvram_safe_get("ftp_port"), chain_in_accept);
971 if (!c) break;
972 p = c + 1;
973 } while (*p);
975 #endif
977 // IGMP query from WAN interface
978 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
979 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
980 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
983 // Routing protocol, RIP, accept
984 if (nvram_invmatch("dr_wan_rx", "0")) {
985 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
988 // if logging
989 if (*chain_in_drop == 'l') {
990 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
993 // default policy: DROP
996 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
997 static void clampmss(void)
999 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1000 #ifdef TCONFIG_IPV6
1001 switch (get_ipv6_service()) {
1002 case IPV6_ANYCAST_6TO4:
1003 case IPV6_6IN4:
1004 ip6t_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1005 break;
1007 #endif
1010 static void filter_forward(void)
1012 char dst[64];
1013 char src[64];
1014 char t[512];
1015 char *p, *c;
1016 int i;
1018 if (nvram_match("cstats_enable", "1")) {
1019 ipt_account();
1022 #ifdef TCONFIG_IPV6
1023 ip6t_write(
1024 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
1025 #endif
1027 ip46t_write(
1028 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
1029 lanface, lanface);
1030 #ifdef TCONFIG_VLAN
1031 if (strcmp(lan1face,"")!=0)
1032 ip46t_write(
1033 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1034 lan1face, lan1face);
1035 if (strcmp(lan2face,"")!=0)
1036 ip46t_write(
1037 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1038 lan2face, lan2face);
1039 if (strcmp(lan3face,"")!=0)
1040 ip46t_write(
1041 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1042 lan3face, lan3face);
1044 char lanAccess[17] = "0000000000000000";
1045 const char *d, *sbr, *saddr, *dbr, *daddr, *desc;
1046 char *nv, *nvp, *b;
1047 int n;
1048 nvp = nv = strdup(nvram_safe_get("lan_access"));
1049 if (nv) {
1050 while ((b = strsep(&nvp, ">")) != NULL) {
1052 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
1054 1 = enabled
1055 0 = src bridge
1056 1.2.3.4 = src addr
1057 1 = dst bridge
1058 5.6.7.8 = dst addr
1059 desc = desc
1061 n = vstrsep(b, "<", &d, &sbr, &saddr, &dbr, &daddr, &desc);
1062 if (*d != '1')
1063 continue;
1064 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4|IPT_V6, 0, "LAN access", desc))
1065 continue;
1066 if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V4|IPT_V6, 0, "LAN access", desc))
1067 continue;
1069 ip46t_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
1070 "br",
1071 sbr,
1072 "br",
1073 dbr,
1074 src,
1075 dst);
1077 if ((strcmp(src,"")==0) && (strcmp(dst,"")==0))
1078 lanAccess[((*sbr-48)+(*dbr-48)*4)] = '1';
1082 free(nv);
1083 #endif
1085 ip46t_write(
1086 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
1088 // clamp tcp mss to pmtu
1089 clampmss();
1091 if (wanup) {
1092 ipt_restrictions();
1094 ipt_layer7_inbound();
1097 ipt_webmon();
1099 ip46t_write(
1100 ":wanin - [0:0]\n"
1101 ":wanout - [0:0]\n"
1102 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1104 #ifdef TCONFIG_VLAN
1105 char lanN_ifname[] = "lanXX_ifname";
1106 char br;
1107 for(br=0 ; br<=3 ; br++) {
1108 char bridge[2] = "0";
1109 if (br!=0)
1110 bridge[0]+=br;
1111 else
1112 strcpy(bridge, "");
1114 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1115 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1116 char lanN_ifname2[] = "lanXX_ifname";
1117 char br2;
1118 for(br2=0 ; br2<=3 ; br2++) {
1119 if (br==br2) continue;
1121 if (lanAccess[((br)+(br2)*4)] == '1') continue;
1123 char bridge2[2] = "0";
1124 if (br2!=0)
1125 bridge2[0]+=br2;
1126 else
1127 strcpy(bridge2, "");
1129 sprintf(lanN_ifname2, "lan%s_ifname", bridge2);
1130 if (strncmp(nvram_safe_get(lanN_ifname2), "br", 2) == 0) {
1131 ip46t_write("-A FORWARD -i %s -o %s -j DROP\n",
1132 nvram_safe_get(lanN_ifname),
1133 nvram_safe_get(lanN_ifname2));
1136 // ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1139 #endif
1141 #ifdef TCONFIG_IPV6
1142 // Filter out invalid WAN->WAN connections
1143 if (*wan6face)
1144 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face, lanface, chain_in_drop);
1146 #ifdef LINUX26
1147 modprobe("xt_length");
1148 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1149 #endif
1151 // ICMPv6 rules
1152 for (i = 0; i < sizeof(allowed_icmpv6)/sizeof(int); ++i) {
1153 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[i], chain_in_accept);
1156 if (*wan6face) {
1157 ip6t_write(
1158 "-A FORWARD -i %s -j wanin\n" // generic from wan
1159 "-A FORWARD -o %s -j wanout\n", // generic to wan
1160 wan6face, wan6face);
1162 #endif
1164 for (i = 0; i < wanfaces.count; ++i) {
1165 if (*(wanfaces.iface[i].name)) {
1166 ipt_write(
1167 "-A FORWARD -i %s -j wanin\n" // generic from wan
1168 "-A FORWARD -o %s -j wanout\n", // generic to wan
1169 wanfaces.iface[i].name, wanfaces.iface[i].name);
1173 #ifdef TCONFIG_VLAN
1174 for(br=0 ; br<=3 ; br++) {
1175 char bridge[2] = "0";
1176 if (br!=0)
1177 bridge[0]+=br;
1178 else
1179 strcpy(bridge, "");
1181 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1182 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1183 ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1186 #else
1187 ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1188 #endif
1190 // #ifdef TCONFIG_VLAN
1191 /* for (i = 0; i < wanfaces.count; ++i) {
1192 if (*(wanfaces.iface[i].name)) {
1193 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wanfaces.iface[i].name, chain_out_accept);
1194 if (strcmp(lan1face,"")!=0)
1195 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wanfaces.iface[i].name, chain_out_accept);
1196 if (strcmp(lan2face,"")!=0)
1197 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wanfaces.iface[i].name, chain_out_accept);
1198 if (strcmp(lan3face,"")!=0)
1199 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wanfaces.iface[i].name, chain_out_accept);
1203 // #else
1204 // ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1205 // #endif
1207 #ifdef TCONFIG_IPV6
1208 //IPv6 forward LAN->WAN accept
1209 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wan6face, chain_out_accept);
1210 #ifdef TCONFIG_VLAN
1211 if (strcmp(lan1face,"")!=0)
1212 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wan6face, chain_out_accept);
1213 if (strcmp(lan2face,"")!=0)
1214 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wan6face, chain_out_accept);
1215 if (strcmp(lan3face,"")!=0)
1216 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wan6face, chain_out_accept);
1217 #endif
1218 #endif
1220 if (nvram_get_int("upnp_enable") & 3) {
1221 ipt_write(":upnp - [0:0]\n");
1222 for (i = 0; i < wanfaces.count; ++i) {
1223 if (*(wanfaces.iface[i].name)) {
1224 ipt_write("-A FORWARD -i %s -j upnp\n",
1225 wanfaces.iface[i].name);
1230 if (wanup) {
1231 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1232 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
1234 ipt_triggered(IPT_TABLE_FILTER);
1235 ipt_forward(IPT_TABLE_FILTER);
1236 #ifdef TCONFIG_IPV6
1237 ip6t_forward();
1238 #endif
1240 if (dmz_dst(dst)) {
1241 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
1242 p = t;
1243 do {
1244 if ((c = strchr(p, ',')) != NULL) *c = 0;
1245 if (ipt_source_strict(p, src, "dmz", NULL))
1246 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface, src, dst, chain_in_accept);
1247 if (!c) break;
1248 p = c + 1;
1249 } while (*p);
1253 // default policy: DROP
1256 static void filter_log(void)
1258 int n;
1259 char limit[128];
1261 n = nvram_get_int("log_limit");
1262 if ((n >= 1) && (n <= 9999)) {
1263 sprintf(limit, "-m limit --limit %d/m", n);
1265 else {
1266 limit[0] = 0;
1269 #ifdef TCONFIG_IPV6
1270 modprobe("ip6t_LOG");
1271 #endif
1272 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
1273 ip46t_write(
1274 ":logdrop - [0:0]\n"
1275 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1276 #ifdef LINUX26
1277 " --log-macdecode"
1278 #endif
1279 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1280 "-A logdrop -j DROP\n"
1281 ":logreject - [0:0]\n"
1282 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1283 #ifdef LINUX26
1284 " --log-macdecode"
1285 #endif
1286 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1287 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1288 limit, limit);
1290 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
1291 ip46t_write(
1292 ":logaccept - [0:0]\n"
1293 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1294 #ifdef LINUX26
1295 " --log-macdecode"
1296 #endif
1297 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1298 "-A logaccept -j ACCEPT\n",
1299 limit);
1303 #ifdef TCONFIG_IPV6
1304 static void filter6_input(void)
1306 char s[128];
1307 char t[512];
1308 char *en;
1309 char *sec;
1310 char *hit;
1311 int n;
1312 char *p, *c;
1314 // RFC-4890, sec. 4.4.1
1315 const int allowed_local_icmpv6[] =
1316 { 130, 131, 132, 133, 134, 135, 136,
1317 141, 142, 143,
1318 148, 149, 151, 152, 153 };
1320 ip6t_write(
1321 "-A INPUT -m rt --rt-type 0 -j %s\n"
1322 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1323 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1324 chain_in_drop);
1326 #ifdef LINUX26
1327 modprobe("xt_length");
1328 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1329 #endif
1331 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
1332 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
1333 #ifdef LINUX26
1334 modprobe("xt_recent");
1335 #else
1336 modprobe("ipt_recent");
1337 #endif
1339 ip6t_write(
1340 "-N shlimit\n"
1341 "-A shlimit -m recent --set --name shlimit\n"
1342 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1343 atoi(hit) + 1, sec, chain_in_drop);
1345 if (n & 1) {
1346 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
1347 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1348 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1351 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"));
1354 #ifdef TCONFIG_FTP
1355 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
1356 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
1357 #ifdef LINUX26
1358 modprobe("xt_recent");
1359 #else
1360 modprobe("ipt_recent");
1361 #endif
1363 ip6t_write(
1364 "-N ftplimit\n"
1365 "-A ftplimit -m recent --set --name ftp\n"
1366 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1367 atoi(hit) + 1, sec, chain_in_drop);
1368 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1370 #endif // TCONFIG_FTP
1372 ip6t_write(
1373 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1374 "-A INPUT -i lo -j ACCEPT\n",
1375 lanface );
1377 switch (get_ipv6_service()) {
1378 case IPV6_ANYCAST_6TO4:
1379 case IPV6_NATIVE_DHCP:
1380 // allow responses from the dhcpv6 server
1381 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept);
1382 break;
1385 // ICMPv6 rules
1386 const int allowed_icmpv6[6] = { 1, 2, 3, 4, 128, 129 };
1387 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
1388 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
1390 for (n = 0; n < sizeof(allowed_local_icmpv6)/sizeof(int); n++) {
1391 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6[n], chain_in_accept);
1394 // Remote Managment
1395 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1396 p = t;
1397 do {
1398 if ((c = strchr(p, ',')) != NULL) *c = 0;
1400 if (ip6t_source(p, s, "remote management", NULL)) {
1402 if (remotemanage) {
1403 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1404 s, nvram_safe_get("http_wanport"), chain_in_accept);
1407 if (nvram_get_int("sshd_remote")) {
1408 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1409 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1413 if (!c) break;
1414 p = c + 1;
1415 } while (*p);
1417 #ifdef TCONFIG_FTP
1418 // FTP server
1419 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1420 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1421 p = t;
1422 do {
1423 if ((c = strchr(p, ',')) != NULL) *c = 0;
1424 if (ip6t_source(p, s, "ftp", "remote access")) {
1425 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1426 s, nvram_safe_get("ftp_port"), chain_in_accept);
1428 if (!c) break;
1429 p = c + 1;
1430 } while (*p);
1432 #endif
1434 // if logging
1435 if (*chain_in_drop == 'l') {
1436 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
1439 // default policy: DROP
1442 #endif
1444 static void filter_table(void)
1446 ip46t_write(
1447 "*filter\n"
1448 ":INPUT DROP [0:0]\n"
1449 ":OUTPUT ACCEPT [0:0]\n"
1452 filter_log();
1454 filter_input();
1455 #ifdef TCONFIG_IPV6
1456 filter6_input();
1457 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop);
1458 #endif
1460 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
1461 ip46t_write(":FORWARD DROP [0:0]\n");
1462 filter_forward();
1464 else {
1465 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1466 clampmss();
1468 ip46t_write("COMMIT\n");
1471 // -----------------------------------------------------------------------------
1473 int start_firewall(void)
1475 DIR *dir;
1476 struct dirent *dirent;
1477 char s[256];
1478 char *c, *wanface;
1479 int n;
1480 int wanproto;
1481 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
1482 #ifdef TCONFIG_IPV6
1483 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
1484 #endif
1486 simple_lock("firewall");
1487 simple_lock("restrictions");
1489 wanproto = get_wan_proto();
1490 wanup = check_wanup();
1492 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1494 /* NAT performance tweaks
1495 * These values can be overriden later if needed via firewall script
1497 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1498 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1499 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1500 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1501 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1502 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1503 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1504 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1505 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1506 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1507 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1508 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1510 /* DoS-related tweaks */
1511 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1512 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1513 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1515 wanproto = get_wan_proto();
1516 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto == WP_DISABLED || wanproto == WP_STATIC) ? "0" : "1", 0, 0);
1518 #ifdef TCONFIG_EMF
1519 /* Force IGMPv2 due EMF limitations */
1520 if (nvram_get_int("emf_enable")) {
1521 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1522 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1524 #endif
1526 n = nvram_get_int("log_in");
1527 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1528 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1530 n = nvram_get_int("log_out");
1531 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1532 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1533 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1535 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1537 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1538 #ifdef TCONFIG_VLAN
1539 strlcpy(lan1face, nvram_safe_get("lan1_ifname"), IFNAMSIZ);
1540 strlcpy(lan2face, nvram_safe_get("lan2_ifname"), IFNAMSIZ);
1541 strlcpy(lan3face, nvram_safe_get("lan3_ifname"), IFNAMSIZ);
1542 #endif
1544 memcpy(&wanfaces, get_wanfaces(), sizeof(wanfaces));
1545 wanface = wanfaces.iface[0].name;
1546 #ifdef TCONFIG_IPV6
1547 strlcpy(wan6face, get_wan6face(), sizeof(wan6face));
1548 #endif
1550 #ifdef LINUX26
1551 can_enable_fastnat = 1;
1552 #endif
1554 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1555 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1556 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1557 #ifdef TCONFIG_VLAN
1559 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1560 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1561 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1563 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1564 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1565 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1567 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1568 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1569 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1571 #endif
1574 block obviously spoofed IP addresses
1576 rp_filter - BOOLEAN
1577 1 - do source validation by reversed path, as specified in RFC1812
1578 Recommended option for single homed hosts and stub network
1579 routers. Could cause troubles for complicated (not loop free)
1580 networks running a slow unreliable protocol (sort of RIP),
1581 or using static routes.
1582 0 - No source validation.
1584 c = nvram_get("wan_ifname");
1585 /* mcast needs rp filter to be turned off only for non default iface */
1586 if (!(nvram_match("multicast_pass", "1")) || !(nvram_match("udpxy_enable", "1")) || strcmp(wanface, c) == 0) c = NULL;
1588 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1589 while ((dirent = readdir(dir)) != NULL) {
1590 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
1591 f_write_string(s, (c && strcmp(dirent->d_name, c) == 0) ? "0" : "1", 0, 0);
1593 closedir(dir);
1596 remotemanage = 0;
1597 gateway_mode = !nvram_match("wk_mode", "router");
1598 if (gateway_mode) {
1599 /* Remote management */
1600 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1601 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1604 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1605 notice_set("iptables", "Unable to create iptables restore file");
1606 simple_unlock("firewall");
1607 return 0;
1610 #ifdef TCONFIG_IPV6
1611 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1612 notice_set("ip6tables", "Unable to create ip6tables restore file");
1613 simple_unlock("firewall");
1614 return 0;
1616 modprobe("nf_conntrack_ipv6");
1617 modprobe("ip6t_REJECT");
1618 #endif
1619 /*Deon Thomas attempt to start xt_IMQ and imq */
1620 /*shibby - fix modprobing IMQ for kernel 2.4 */
1621 modprobe("imq");
1622 #ifdef LINUX26
1623 modprobe("xt_IMQ");
1624 #else
1625 modprobe("ipt_IMQ");
1626 #endif
1628 mangle_table();
1629 nat_table();
1630 filter_table();
1632 fclose(ipt_file);
1633 ipt_file = NULL;
1635 #ifdef TCONFIG_IPV6
1636 fclose(ip6t_file);
1637 ip6t_file = NULL;
1638 #endif
1640 #ifdef DEBUG_IPTFILE
1641 if (debug_only) {
1642 simple_unlock("firewall");
1643 simple_unlock("restrictions");
1644 return 0;
1646 #endif
1648 save_webmon();
1650 if (nvram_get_int("upnp_enable") & 3) {
1651 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1652 if (killall("miniupnpd", SIGUSR2) == 0) {
1653 f_wait_notexists("/etc/upnp/save", 5);
1657 notice_set("iptables", "");
1658 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1659 led(LED_DIAG, 0);
1660 notice_set("iptables", "");
1662 else {
1663 sprintf(s, "%s.error", ipt_fname);
1664 rename(ipt_fname, s);
1665 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1666 led(LED_DIAG, 1);
1670 -P INPUT DROP
1671 -F INPUT
1672 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1673 -A INPUT -i br0 -j ACCEPT
1675 -P FORWARD DROP
1676 -F FORWARD
1677 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1678 -A FORWARD -i br0 -j ACCEPT
1683 #ifdef TCONFIG_IPV6
1684 if (ipv6_enabled()) {
1685 notice_set("ip6tables", "");
1686 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1687 notice_set("ip6tables", "");
1689 else {
1690 sprintf(s, "%s.error", ip6t_fname);
1691 rename(ip6t_fname, s);
1692 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1693 led(LED_DIAG, 1);
1696 else {
1697 eval("ip6tables", "-F");
1698 eval("ip6tables", "-t", "mangle", "-F");
1700 #endif
1702 if (nvram_get_int("upnp_enable") & 3) {
1703 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1704 killall("miniupnpd", SIGUSR2);
1707 simple_unlock("restrictions");
1708 sched_restrictions();
1709 enable_ip_forward();
1711 led(LED_DMZ, dmz_dst(NULL));
1713 #ifdef TCONFIG_IPV6
1714 modprobe_r("nf_conntrack_ipv6");
1715 modprobe_r("ip6t_LOG");
1716 modprobe_r("ip6t_REJECT");
1717 #endif
1718 #ifdef LINUX26
1719 modprobe_r("xt_layer7");
1720 modprobe_r("xt_recent");
1721 modprobe_r("xt_HL");
1722 modprobe_r("xt_length");
1723 modprobe_r("xt_web");
1724 modprobe_r("xt_webmon");
1725 modprobe_r("xt_dscp");
1726 #else
1727 modprobe_r("ipt_layer7");
1728 modprobe_r("ipt_recent");
1729 modprobe_r("ipt_TTL");
1730 modprobe_r("ipt_web");
1731 modprobe_r("ipt_webmon");
1732 modprobe_r("ipt_dscp");
1733 #endif
1734 modprobe_r("ipt_ipp2p");
1736 unlink("/var/webmon/domain");
1737 unlink("/var/webmon/search");
1739 #ifdef TCONFIG_OPENVPN
1740 run_vpn_firewall_scripts();
1741 #endif
1742 run_nvscript("script_fire", NULL, 1);
1744 start_arpbind();
1746 #ifdef LINUX26
1747 allow_fastnat("firewall", can_enable_fastnat);
1748 try_enabling_fastnat();
1749 #endif
1751 simple_unlock("firewall");
1752 return 0;
1755 int stop_firewall(void)
1757 led(LED_DMZ, 0);
1758 return 0;
1761 #ifdef DEBUG_IPTFILE
1762 void create_test_iptfile(void)
1764 debug_only = 1;
1765 start_firewall();
1766 debug_only = 0;
1768 #endif