OpenSSL 1.0.1 update
[tomato.git] / release / src / router / rc / firewall.c
blob38789b9b1fe90c2c6ca9b7dd27d271ab03ebec21
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();
563 p = nvram_safe_get("nf_ttl");
564 if (strncmp(p, "c:", 2) == 0) {
565 p += 2;
566 ttl = atoi(p);
567 p = (ttl >= 0 && ttl <= 255) ? "set" : NULL;
569 else if ((ttl = atoi(p)) != 0) {
570 if (ttl > 0) {
571 p = "inc";
573 else {
574 ttl = -ttl;
575 p = "dec";
577 if (ttl > 255) p = NULL;
579 else p = NULL;
581 if (p) {
582 #ifdef LINUX26
583 modprobe("xt_HL");
584 #else
585 modprobe("ipt_TTL");
586 #endif
587 // set TTL on primary WAN iface only
588 wanface = wanfaces.iface[0].name;
589 ipt_write(
590 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
591 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
592 wanface, p, ttl,
593 wanface, p, ttl);
594 #ifdef TCONFIG_IPV6
595 // FIXME: IPv6 HL should be configurable separately from TTL.
596 // disable it until GUI setting is implemented.
597 #if 0
598 ip6t_write(
599 "-I PREROUTING -i %s -j HL --hl-%s %d\n"
600 "-I POSTROUTING -o %s -j HL --hl-%s %d\n",
601 wan6face, p, ttl,
602 wan6face, p, ttl);
603 #endif
604 #endif
608 ip46t_write("COMMIT\n");
611 // -----------------------------------------------------------------------------
612 // NAT
613 // -----------------------------------------------------------------------------
615 static void nat_table(void)
617 char lanaddr[32];
618 char lanmask[32];
619 #ifdef TCONFIG_VLAN
620 char lan1addr[32];
621 char lan1mask[32];
622 char lan2addr[32];
623 char lan2mask[32];
624 char lan3addr[32];
625 char lan3mask[32];
626 #endif
627 char dst[64];
628 char src[64];
629 char t[512];
630 char *p, *c;
631 int i;
633 ipt_write("*nat\n"
634 ":PREROUTING ACCEPT [0:0]\n"
635 ":POSTROUTING ACCEPT [0:0]\n"
636 ":OUTPUT ACCEPT [0:0]\n"
637 ":%s - [0:0]\n",
638 chain_wan_prerouting);
640 if (gateway_mode) {
641 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
642 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
643 #ifdef TCONFIG_VLAN
644 strlcpy(lan1addr, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr));
645 strlcpy(lan1mask, nvram_safe_get("lan1_netmask"), sizeof(lan1mask));
646 strlcpy(lan2addr, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr));
647 strlcpy(lan2mask, nvram_safe_get("lan2_netmask"), sizeof(lan2mask));
648 strlcpy(lan3addr, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr));
649 strlcpy(lan3mask, nvram_safe_get("lan3_netmask"), sizeof(lan3mask));
650 #endif
652 for (i = 0; i < wanfaces.count; ++i) {
653 if (*(wanfaces.iface[i].name)) {
654 // Drop incoming packets which destination IP address is to our LAN side directly
655 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
656 wanfaces.iface[i].name,
657 lanaddr, lanmask); // note: ipt will correct lanaddr
658 #ifdef TCONFIG_VLAN
659 if(strcmp(lan1addr,"")!=0)
660 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
661 wanfaces.iface[i].name,
662 lan1addr, lan1mask);
663 if(strcmp(lan2addr,"")!=0)
664 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
665 wanfaces.iface[i].name,
666 lan2addr, lan2mask);
667 if(strcmp(lan3addr,"")!=0)
668 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
669 wanfaces.iface[i].name,
670 lan3addr, lan3mask);
671 #endif
672 // chain_wan_prerouting
673 if (wanup) {
674 ipt_write("-A PREROUTING -d %s -j %s\n",
675 wanfaces.iface[i].ip, chain_wan_prerouting);
680 if (wanup) {
681 if (nvram_match("dns_intcpt", "1")) {
682 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
683 lanaddr, lanmask,
684 lanaddr, lanmask,
685 lanaddr);
686 #ifdef TCONFIG_VLAN
687 if(strcmp(lan1addr,"")!=0)
688 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
689 lan1addr, lan1mask,
690 lan1addr, lan1mask,
691 lan1addr);
692 if(strcmp(lan2addr,"")!=0)
693 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
694 lan2addr, lan2mask,
695 lan2addr, lan2mask,
696 lan2addr);
697 if(strcmp(lan3addr,"")!=0)
698 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
699 lan3addr, lan3mask,
700 lan3addr, lan3mask,
701 lan3addr);
702 #endif
705 // ICMP packets are always redirected to INPUT chains
706 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
708 ipt_forward(IPT_TABLE_NAT);
709 ipt_triggered(IPT_TABLE_NAT);
712 if (nvram_get_int("upnp_enable") & 3) {
713 ipt_write(":upnp - [0:0]\n");
715 for (i = 0; i < wanfaces.count; ++i) {
716 if (*(wanfaces.iface[i].name)) {
717 if (wanup) {
718 // ! for loopback (all) to work
719 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces.iface[i].ip);
721 else {
722 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces.iface[i].name);
728 if (wanup) {
729 if (dmz_dst(dst)) {
730 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
731 p = t;
732 do {
733 if ((c = strchr(p, ',')) != NULL) *c = 0;
734 if (ipt_source_strict(p, src, "dmz", NULL))
735 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
736 if (!c) break;
737 p = c + 1;
738 } while (*p);
742 p = "";
743 #ifdef TCONFIG_IPV6
744 switch (get_ipv6_service()) {
745 case IPV6_6IN4:
746 // avoid NATing proto-41 packets when using 6in4 tunnel
747 p = "-p ! 41";
748 break;
750 #endif
752 char *modem_ipaddr;
753 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
754 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
755 && (!foreach_wif(1, NULL, is_sta)) )
756 ipt_write("-A POSTROUTING -o %s -d %s -j MASQUERADE\n", nvram_safe_get("wan_ifname"), modem_ipaddr);
758 for (i = 0; i < wanfaces.count; ++i) {
759 if (*(wanfaces.iface[i].name)) {
760 if ((!wanup) || (nvram_get_int("ne_snat") != 1))
761 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p, wanfaces.iface[i].name);
762 else
763 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p, wanfaces.iface[i].name, wanfaces.iface[i].ip);
767 switch (nvram_get_int("nf_loopback")) {
768 case 1: // 1 = forwarded-only
769 case 2: // 2 = disable
770 break;
771 default: // 0 = all (same as block_loopback=0)
772 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
773 lanface,
774 lanaddr, lanmask,
775 lanaddr, lanmask,
776 lanaddr);
777 #ifdef TCONFIG_VLAN
778 if (strcmp(lan1face,"")!=0)
779 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
780 lan1face,
781 lan1addr, lan1mask,
782 lan1addr, lan1mask,
783 lan1addr);
784 if (strcmp(lan2face,"")!=0)
785 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
786 lan2face,
787 lan2addr, lan2mask,
788 lan2addr, lan2mask,
789 lan2addr);
790 if (strcmp(lan3face,"")!=0)
791 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
792 lan3face,
793 lan3addr, lan3mask,
794 lan3addr, lan3mask,
795 lan3addr);
796 #endif
797 break;
800 ipt_write("COMMIT\n");
803 // -----------------------------------------------------------------------------
804 // FILTER
805 // -----------------------------------------------------------------------------
807 static void filter_input(void)
809 char s[64];
810 char t[512];
811 char *en;
812 char *sec;
813 char *hit;
814 int n;
815 char *p, *c;
817 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
818 for (n = 0; n < wanfaces.count; ++n) {
819 if (*(wanfaces.iface[n].name)) {
820 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanfaces.iface[n].ip);
821 #ifdef TCONFIG_VLAN
822 if (strcmp(lan1face,"")!=0)
823 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face, wanfaces.iface[n].ip);
824 if (strcmp(lan2face,"")!=0)
825 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face, wanfaces.iface[n].ip);
826 if (strcmp(lan3face,"")!=0)
827 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face, wanfaces.iface[n].ip);
828 #endif
833 ipt_write(
834 "-A INPUT -m state --state INVALID -j DROP\n"
835 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
837 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
838 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
840 ? what if the user uses the start button in GUI ?
841 if (nvram_get_int("telnetd_eas"))
842 if (nvram_get_int("sshd_eas"))
844 #ifdef LINUX26
845 modprobe("xt_recent");
846 #else
847 modprobe("ipt_recent");
848 #endif
850 ipt_write(
851 "-N shlimit\n"
852 "-A shlimit -m recent --set --name shlimit\n"
853 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
854 atoi(hit) + 1, sec, chain_in_drop);
856 if (n & 1) {
857 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
858 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
859 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
862 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
865 #ifdef TCONFIG_FTP
866 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
867 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
868 #ifdef LINUX26
869 modprobe("xt_recent");
870 #else
871 modprobe("ipt_recent");
872 #endif
874 ipt_write(
875 "-N ftplimit\n"
876 "-A ftplimit -m recent --set --name ftp\n"
877 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
878 atoi(hit) + 1, sec, chain_in_drop);
879 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
881 #endif
883 ipt_write(
884 "-A INPUT -i lo -j ACCEPT\n"
885 "-A INPUT -i %s -j ACCEPT\n",
886 lanface);
887 #ifdef TCONFIG_VLAN
888 if (strcmp(lan1face,"")!=0)
889 ipt_write(
890 "-A INPUT -i %s -j ACCEPT\n",
891 lan1face);
892 if (strcmp(lan2face,"")!=0)
893 ipt_write(
894 "-A INPUT -i %s -j ACCEPT\n",
895 lan2face);
896 if (strcmp(lan3face,"")!=0)
897 ipt_write(
898 "-A INPUT -i %s -j ACCEPT\n",
899 lan3face);
900 #endif
902 #ifdef TCONFIG_IPV6
903 n = get_ipv6_service();
904 switch (n) {
905 case IPV6_ANYCAST_6TO4:
906 case IPV6_6IN4:
907 // Accept ICMP requests from the remote tunnel endpoint
908 if (n == IPV6_ANYCAST_6TO4)
909 sprintf(s, "192.88.99.%d", nvram_get_int("ipv6_relay"));
910 else
911 strlcpy(s, nvram_safe_get("ipv6_tun_v4end"), sizeof(s));
912 if (*s && strcmp(s, "0.0.0.0") != 0)
913 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s, chain_in_accept);
914 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept);
915 break;
917 #endif
919 // ICMP request from WAN interface
920 if (nvram_match("block_wan", "0")) {
921 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
922 ipt_write("-A INPUT -p icmp -m limit --limit 1/second -j %s\n", chain_in_accept);
923 // allow udp traceroute packets
924 ipt_write("-A INPUT -p udp --dport 33434:33534 -m limit --limit 5/second -j %s\n", chain_in_accept);
927 /* Accept incoming packets from broken dhcp servers, which are sending replies
928 * from addresses other than used for query. This could lead to a lower level
929 * of security, so allow to disable it via nvram variable.
931 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
932 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
935 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
936 p = t;
937 do {
938 if ((c = strchr(p, ',')) != NULL) *c = 0;
940 if (ipt_source(p, s, "remote management", NULL)) {
942 if (remotemanage) {
943 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
944 s, nvram_safe_get("http_wanport"), chain_in_accept);
947 if (nvram_get_int("sshd_remote")) {
948 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
949 s, nvram_safe_get("sshd_rport"), chain_in_accept);
953 if (!c) break;
954 p = c + 1;
955 } while (*p);
957 #ifdef TCONFIG_FTP // !!TB - FTP Server
958 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
959 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
960 p = t;
961 do {
962 if ((c = strchr(p, ',')) != NULL) *c = 0;
963 if (ipt_source(p, s, "ftp", "remote access")) {
964 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
965 s, nvram_safe_get("ftp_port"), chain_in_accept);
967 if (!c) break;
968 p = c + 1;
969 } while (*p);
971 #endif
973 // IGMP query from WAN interface
974 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
975 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
976 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
979 // Routing protocol, RIP, accept
980 if (nvram_invmatch("dr_wan_rx", "0")) {
981 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
984 // if logging
985 if (*chain_in_drop == 'l') {
986 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
989 // default policy: DROP
992 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
993 static void clampmss(void)
995 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
996 #ifdef TCONFIG_IPV6
997 switch (get_ipv6_service()) {
998 case IPV6_ANYCAST_6TO4:
999 case IPV6_6IN4:
1000 ip6t_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
1001 break;
1003 #endif
1006 static void filter_forward(void)
1008 char dst[64];
1009 char src[64];
1010 char t[512];
1011 char *p, *c;
1012 int i;
1014 if (nvram_match("cstats_enable", "1")) {
1015 ipt_account();
1018 #ifdef TCONFIG_IPV6
1019 ip6t_write(
1020 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
1021 #endif
1023 ip46t_write(
1024 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
1025 lanface, lanface);
1026 #ifdef TCONFIG_VLAN
1027 if (strcmp(lan1face,"")!=0)
1028 ip46t_write(
1029 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1030 lan1face, lan1face);
1031 if (strcmp(lan2face,"")!=0)
1032 ip46t_write(
1033 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1034 lan2face, lan2face);
1035 if (strcmp(lan3face,"")!=0)
1036 ip46t_write(
1037 "-A FORWARD -i %s -o %s -j ACCEPT\n",
1038 lan3face, lan3face);
1040 char lanAccess[17] = "0000000000000000";
1041 const char *d, *sbr, *saddr, *dbr, *daddr, *desc;
1042 char *nv, *nvp, *b;
1043 int n;
1044 nvp = nv = strdup(nvram_safe_get("lan_access"));
1045 if (nv) {
1046 while ((b = strsep(&nvp, ">")) != NULL) {
1048 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
1050 1 = enabled
1051 0 = src bridge
1052 1.2.3.4 = src addr
1053 1 = dst bridge
1054 5.6.7.8 = dst addr
1055 desc = desc
1057 n = vstrsep(b, "<", &d, &sbr, &saddr, &dbr, &daddr, &desc);
1058 if (*d != '1')
1059 continue;
1060 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4|IPT_V6, 0, "LAN access", desc))
1061 continue;
1062 if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V4|IPT_V6, 0, "LAN access", desc))
1063 continue;
1065 //ipv4 only
1066 ipt_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
1067 "br",
1068 sbr,
1069 "br",
1070 dbr,
1071 src,
1072 dst);
1074 if ((strcmp(src,"")==0) && (strcmp(dst,"")==0))
1075 lanAccess[((*sbr-48)+(*dbr-48)*4)] = '1';
1079 free(nv);
1080 #endif
1082 ip46t_write(
1083 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
1085 // clamp tcp mss to pmtu
1086 clampmss();
1088 if (wanup) {
1089 ipt_restrictions();
1091 ipt_layer7_inbound();
1094 ipt_webmon();
1096 ip46t_write(
1097 ":wanin - [0:0]\n"
1098 ":wanout - [0:0]\n"
1099 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1101 #ifdef TCONFIG_VLAN
1102 char lanN_ifname[] = "lanXX_ifname";
1103 char br;
1104 for(br=0 ; br<=3 ; br++) {
1105 char bridge[2] = "0";
1106 if (br!=0)
1107 bridge[0]+=br;
1108 else
1109 strcpy(bridge, "");
1111 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1112 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1113 char lanN_ifname2[] = "lanXX_ifname";
1114 char br2;
1115 for(br2=0 ; br2<=3 ; br2++) {
1116 if (br==br2) continue;
1118 if (lanAccess[((br)+(br2)*4)] == '1') continue;
1120 char bridge2[2] = "0";
1121 if (br2!=0)
1122 bridge2[0]+=br2;
1123 else
1124 strcpy(bridge2, "");
1126 sprintf(lanN_ifname2, "lan%s_ifname", bridge2);
1127 if (strncmp(nvram_safe_get(lanN_ifname2), "br", 2) == 0) {
1128 ip46t_write("-A FORWARD -i %s -o %s -j DROP\n",
1129 nvram_safe_get(lanN_ifname),
1130 nvram_safe_get(lanN_ifname2));
1133 // ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1136 #endif
1138 #ifdef TCONFIG_PPTPD
1139 //Add for pptp server
1140 if (nvram_match("pptpd_enable", "1")) {
1141 ipt_write("-A INPUT -p tcp --dport 1723 -j ACCEPT\n");
1142 ipt_write("-A INPUT -p 47 -j ACCEPT\n");
1144 #endif
1146 #ifdef TCONFIG_IPV6
1147 // Filter out invalid WAN->WAN connections
1148 if (*wan6face)
1149 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face, lanface, chain_in_drop);
1151 #ifdef LINUX26
1152 modprobe("xt_length");
1153 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1154 #endif
1156 // ICMPv6 rules
1157 for (i = 0; i < sizeof(allowed_icmpv6)/sizeof(int); ++i) {
1158 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[i], chain_in_accept);
1161 if (*wan6face) {
1162 ip6t_write(
1163 "-A FORWARD -i %s -j wanin\n" // generic from wan
1164 "-A FORWARD -o %s -j wanout\n", // generic to wan
1165 wan6face, wan6face);
1167 #endif
1169 for (i = 0; i < wanfaces.count; ++i) {
1170 if (*(wanfaces.iface[i].name)) {
1171 ipt_write(
1172 "-A FORWARD -i %s -j wanin\n" // generic from wan
1173 "-A FORWARD -o %s -j wanout\n", // generic to wan
1174 wanfaces.iface[i].name, wanfaces.iface[i].name);
1178 #ifdef TCONFIG_VLAN
1179 for(br=0 ; br<=3 ; br++) {
1180 char bridge[2] = "0";
1181 if (br!=0)
1182 bridge[0]+=br;
1183 else
1184 strcpy(bridge, "");
1186 sprintf(lanN_ifname, "lan%s_ifname", bridge);
1187 if (strncmp(nvram_safe_get(lanN_ifname), "br", 2) == 0) {
1188 ipt_write("-A FORWARD -i %s -j %s\n", nvram_safe_get(lanN_ifname), chain_out_accept);
1191 #else
1192 ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1193 #endif
1195 // #ifdef TCONFIG_VLAN
1196 /* for (i = 0; i < wanfaces.count; ++i) {
1197 if (*(wanfaces.iface[i].name)) {
1198 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wanfaces.iface[i].name, chain_out_accept);
1199 if (strcmp(lan1face,"")!=0)
1200 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wanfaces.iface[i].name, chain_out_accept);
1201 if (strcmp(lan2face,"")!=0)
1202 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wanfaces.iface[i].name, chain_out_accept);
1203 if (strcmp(lan3face,"")!=0)
1204 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wanfaces.iface[i].name, chain_out_accept);
1208 // #else
1209 // ipt_write("-A FORWARD -i %s -j %s\n", lanface, chain_out_accept);
1210 // #endif
1212 #ifdef TCONFIG_IPV6
1213 //IPv6 forward LAN->WAN accept
1214 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lanface, wan6face, chain_out_accept);
1215 #ifdef TCONFIG_VLAN
1216 if (strcmp(lan1face,"")!=0)
1217 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan1face, wan6face, chain_out_accept);
1218 if (strcmp(lan2face,"")!=0)
1219 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan2face, wan6face, chain_out_accept);
1220 if (strcmp(lan3face,"")!=0)
1221 ip6t_write("-A FORWARD -i %s -o %s -j %s\n", lan3face, wan6face, chain_out_accept);
1222 #endif
1223 #endif
1225 if (nvram_get_int("upnp_enable") & 3) {
1226 ipt_write(":upnp - [0:0]\n");
1227 for (i = 0; i < wanfaces.count; ++i) {
1228 if (*(wanfaces.iface[i].name)) {
1229 ipt_write("-A FORWARD -i %s -j upnp\n",
1230 wanfaces.iface[i].name);
1235 if (wanup) {
1236 if ((nvram_match("multicast_pass", "1")) || (nvram_match("udpxy_enable", "1"))) {
1237 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
1239 ipt_triggered(IPT_TABLE_FILTER);
1240 ipt_forward(IPT_TABLE_FILTER);
1241 #ifdef TCONFIG_IPV6
1242 ip6t_forward();
1243 #endif
1245 if (dmz_dst(dst)) {
1246 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
1247 p = t;
1248 do {
1249 if ((c = strchr(p, ',')) != NULL) *c = 0;
1250 if (ipt_source_strict(p, src, "dmz", NULL))
1251 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface, src, dst, chain_in_accept);
1252 if (!c) break;
1253 p = c + 1;
1254 } while (*p);
1258 // default policy: DROP
1261 static void filter_log(void)
1263 int n;
1264 char limit[128];
1266 n = nvram_get_int("log_limit");
1267 if ((n >= 1) && (n <= 9999)) {
1268 sprintf(limit, "-m limit --limit %d/m", n);
1270 else {
1271 limit[0] = 0;
1274 #ifdef TCONFIG_IPV6
1275 modprobe("ip6t_LOG");
1276 #endif
1277 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
1278 ip46t_write(
1279 ":logdrop - [0:0]\n"
1280 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1281 #ifdef LINUX26
1282 " --log-macdecode"
1283 #endif
1284 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1285 "-A logdrop -j DROP\n"
1286 ":logreject - [0:0]\n"
1287 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1288 #ifdef LINUX26
1289 " --log-macdecode"
1290 #endif
1291 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1292 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1293 limit, limit);
1295 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
1296 ip46t_write(
1297 ":logaccept - [0:0]\n"
1298 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1299 #ifdef LINUX26
1300 " --log-macdecode"
1301 #endif
1302 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1303 "-A logaccept -j ACCEPT\n",
1304 limit);
1308 #ifdef TCONFIG_IPV6
1309 static void filter6_input(void)
1311 char s[128];
1312 char t[512];
1313 char *en;
1314 char *sec;
1315 char *hit;
1316 int n;
1317 char *p, *c;
1319 // RFC-4890, sec. 4.4.1
1320 const int allowed_local_icmpv6[] =
1321 { 130, 131, 132, 133, 134, 135, 136,
1322 141, 142, 143,
1323 148, 149, 151, 152, 153 };
1325 ip6t_write(
1326 "-A INPUT -m rt --rt-type 0 -j %s\n"
1327 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1328 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1329 chain_in_drop);
1331 #ifdef LINUX26
1332 modprobe("xt_length");
1333 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1334 #endif
1336 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
1337 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
1338 #ifdef LINUX26
1339 modprobe("xt_recent");
1340 #else
1341 modprobe("ipt_recent");
1342 #endif
1344 ip6t_write(
1345 "-N shlimit\n"
1346 "-A shlimit -m recent --set --name shlimit\n"
1347 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1348 atoi(hit) + 1, sec, chain_in_drop);
1350 if (n & 1) {
1351 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
1352 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1353 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1356 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"));
1359 #ifdef TCONFIG_FTP
1360 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
1361 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
1362 #ifdef LINUX26
1363 modprobe("xt_recent");
1364 #else
1365 modprobe("ipt_recent");
1366 #endif
1368 ip6t_write(
1369 "-N ftplimit\n"
1370 "-A ftplimit -m recent --set --name ftp\n"
1371 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1372 atoi(hit) + 1, sec, chain_in_drop);
1373 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1375 #endif // TCONFIG_FTP
1377 ip6t_write(
1378 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1379 "-A INPUT -i lo -j ACCEPT\n",
1380 lanface );
1382 switch (get_ipv6_service()) {
1383 case IPV6_ANYCAST_6TO4:
1384 case IPV6_NATIVE_DHCP:
1385 // allow responses from the dhcpv6 server
1386 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept);
1387 break;
1390 // ICMPv6 rules
1391 const int allowed_icmpv6[6] = { 1, 2, 3, 4, 128, 129 };
1392 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
1393 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
1395 for (n = 0; n < sizeof(allowed_local_icmpv6)/sizeof(int); n++) {
1396 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6[n], chain_in_accept);
1399 // Remote Managment
1400 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
1401 p = t;
1402 do {
1403 if ((c = strchr(p, ',')) != NULL) *c = 0;
1405 if (ip6t_source(p, s, "remote management", NULL)) {
1407 if (remotemanage) {
1408 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1409 s, nvram_safe_get("http_wanport"), chain_in_accept);
1412 if (nvram_get_int("sshd_remote")) {
1413 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1414 s, nvram_safe_get("sshd_rport"), chain_in_accept);
1418 if (!c) break;
1419 p = c + 1;
1420 } while (*p);
1422 #ifdef TCONFIG_FTP
1423 // FTP server
1424 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1425 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
1426 p = t;
1427 do {
1428 if ((c = strchr(p, ',')) != NULL) *c = 0;
1429 if (ip6t_source(p, s, "ftp", "remote access")) {
1430 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1431 s, nvram_safe_get("ftp_port"), chain_in_accept);
1433 if (!c) break;
1434 p = c + 1;
1435 } while (*p);
1437 #endif
1439 // if logging
1440 if (*chain_in_drop == 'l') {
1441 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
1444 // default policy: DROP
1447 #endif
1449 static void filter_table(void)
1451 ip46t_write(
1452 "*filter\n"
1453 ":INPUT DROP [0:0]\n"
1454 ":OUTPUT ACCEPT [0:0]\n"
1457 filter_log();
1459 filter_input();
1460 #ifdef TCONFIG_IPV6
1461 filter6_input();
1462 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop);
1463 #endif
1465 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
1466 ip46t_write(":FORWARD DROP [0:0]\n");
1467 filter_forward();
1469 else {
1470 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1471 clampmss();
1473 ip46t_write("COMMIT\n");
1476 // -----------------------------------------------------------------------------
1478 int start_firewall(void)
1480 DIR *dir;
1481 struct dirent *dirent;
1482 char s[256];
1483 char *c, *wanface;
1484 int n;
1485 int wanproto;
1486 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
1487 #ifdef TCONFIG_IPV6
1488 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
1489 #endif
1491 simple_lock("firewall");
1492 simple_lock("restrictions");
1494 wanproto = get_wan_proto();
1495 wanup = check_wanup();
1497 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1499 /* NAT performance tweaks
1500 * These values can be overriden later if needed via firewall script
1502 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1503 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1504 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1505 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1506 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1507 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1508 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1509 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1510 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1511 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1512 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1513 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1515 /* DoS-related tweaks */
1516 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1517 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1518 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1520 wanproto = get_wan_proto();
1521 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto == WP_DISABLED || wanproto == WP_STATIC) ? "0" : "1", 0, 0);
1523 #ifdef TCONFIG_EMF
1524 /* Force IGMPv2 due EMF limitations */
1525 if (nvram_get_int("emf_enable")) {
1526 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1527 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1529 #endif
1531 n = nvram_get_int("log_in");
1532 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1533 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1535 n = nvram_get_int("log_out");
1536 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1537 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1538 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1540 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1542 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1543 #ifdef TCONFIG_VLAN
1544 strlcpy(lan1face, nvram_safe_get("lan1_ifname"), IFNAMSIZ);
1545 strlcpy(lan2face, nvram_safe_get("lan2_ifname"), IFNAMSIZ);
1546 strlcpy(lan3face, nvram_safe_get("lan3_ifname"), IFNAMSIZ);
1547 #endif
1549 memcpy(&wanfaces, get_wanfaces(), sizeof(wanfaces));
1550 wanface = wanfaces.iface[0].name;
1551 #ifdef TCONFIG_IPV6
1552 strlcpy(wan6face, get_wan6face(), sizeof(wan6face));
1553 #endif
1555 #ifdef LINUX26
1556 can_enable_fastnat = 1;
1557 #endif
1559 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1560 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1561 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1562 #ifdef TCONFIG_VLAN
1564 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1565 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1566 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1568 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1569 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1570 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1572 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1573 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1574 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1576 #endif
1579 block obviously spoofed IP addresses
1581 rp_filter - BOOLEAN
1582 1 - do source validation by reversed path, as specified in RFC1812
1583 Recommended option for single homed hosts and stub network
1584 routers. Could cause troubles for complicated (not loop free)
1585 networks running a slow unreliable protocol (sort of RIP),
1586 or using static routes.
1587 0 - No source validation.
1589 c = nvram_get("wan_ifname");
1590 /* mcast needs rp filter to be turned off only for non default iface */
1591 if (!(nvram_match("multicast_pass", "1")) || !(nvram_match("udpxy_enable", "1")) || strcmp(wanface, c) == 0) c = NULL;
1593 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1594 while ((dirent = readdir(dir)) != NULL) {
1595 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
1596 f_write_string(s, (c && strcmp(dirent->d_name, c) == 0) ? "0" : "1", 0, 0);
1598 closedir(dir);
1601 remotemanage = 0;
1602 gateway_mode = !nvram_match("wk_mode", "router");
1603 if (gateway_mode) {
1604 /* Remote management */
1605 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1606 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1609 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1610 notice_set("iptables", "Unable to create iptables restore file");
1611 simple_unlock("firewall");
1612 return 0;
1615 #ifdef TCONFIG_IPV6
1616 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1617 notice_set("ip6tables", "Unable to create ip6tables restore file");
1618 simple_unlock("firewall");
1619 return 0;
1621 modprobe("nf_conntrack_ipv6");
1622 modprobe("ip6t_REJECT");
1623 #endif
1624 /*Start xt_IMQ and imq */
1625 modprobe("imq");
1626 #ifdef LINUX26
1627 modprobe("xt_IMQ");
1628 #else
1629 modprobe("ipt_IMQ");
1630 #endif
1632 mangle_table();
1633 nat_table();
1634 filter_table();
1636 fclose(ipt_file);
1637 ipt_file = NULL;
1639 #ifdef TCONFIG_IPV6
1640 fclose(ip6t_file);
1641 ip6t_file = NULL;
1642 #endif
1644 #ifdef DEBUG_IPTFILE
1645 if (debug_only) {
1646 simple_unlock("firewall");
1647 simple_unlock("restrictions");
1648 return 0;
1650 #endif
1652 save_webmon();
1654 if (nvram_get_int("upnp_enable") & 3) {
1655 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1656 if (killall("miniupnpd", SIGUSR2) == 0) {
1657 f_wait_notexists("/etc/upnp/save", 5);
1661 notice_set("iptables", "");
1662 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1663 led(LED_DIAG, 0);
1664 notice_set("iptables", "");
1666 else {
1667 sprintf(s, "%s.error", ipt_fname);
1668 rename(ipt_fname, s);
1669 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1670 led(LED_DIAG, 1);
1674 -P INPUT DROP
1675 -F INPUT
1676 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1677 -A INPUT -i br0 -j ACCEPT
1679 -P FORWARD DROP
1680 -F FORWARD
1681 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1682 -A FORWARD -i br0 -j ACCEPT
1687 #ifdef TCONFIG_IPV6
1688 if (ipv6_enabled()) {
1689 notice_set("ip6tables", "");
1690 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1691 notice_set("ip6tables", "");
1693 else {
1694 sprintf(s, "%s.error", ip6t_fname);
1695 rename(ip6t_fname, s);
1696 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1697 led(LED_DIAG, 1);
1700 else {
1701 eval("ip6tables", "-F");
1702 eval("ip6tables", "-t", "mangle", "-F");
1704 #endif
1706 if (nvram_get_int("upnp_enable") & 3) {
1707 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1708 killall("miniupnpd", SIGUSR2);
1711 simple_unlock("restrictions");
1712 sched_restrictions();
1713 enable_ip_forward();
1715 led(LED_DMZ, dmz_dst(NULL));
1717 #ifdef TCONFIG_IPV6
1718 modprobe_r("nf_conntrack_ipv6");
1719 modprobe_r("ip6t_LOG");
1720 modprobe_r("ip6t_REJECT");
1721 #endif
1722 #ifdef LINUX26
1723 modprobe_r("xt_layer7");
1724 modprobe_r("xt_recent");
1725 modprobe_r("xt_HL");
1726 modprobe_r("xt_length");
1727 modprobe_r("xt_web");
1728 modprobe_r("xt_webmon");
1729 modprobe_r("xt_dscp");
1730 #else
1731 modprobe_r("ipt_layer7");
1732 modprobe_r("ipt_recent");
1733 modprobe_r("ipt_TTL");
1734 modprobe_r("ipt_web");
1735 modprobe_r("ipt_webmon");
1736 modprobe_r("ipt_dscp");
1737 #endif
1738 modprobe_r("ipt_ipp2p");
1740 unlink("/var/webmon/domain");
1741 unlink("/var/webmon/search");
1743 #ifdef TCONFIG_OPENVPN
1744 run_vpn_firewall_scripts();
1745 #endif
1746 run_nvscript("script_fire", NULL, 1);
1748 start_arpbind();
1750 #ifdef LINUX26
1751 allow_fastnat("firewall", can_enable_fastnat);
1752 try_enabling_fastnat();
1753 #endif
1755 simple_unlock("firewall");
1756 return 0;
1759 int stop_firewall(void)
1761 led(LED_DMZ, 0);
1762 return 0;
1765 #ifdef DEBUG_IPTFILE
1766 void create_test_iptfile(void)
1768 debug_only = 1;
1769 start_firewall();
1770 debug_only = 0;
1772 #endif