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
29 #include <arpa/inet.h>
32 wanface_list_t wanfaces
;
33 char lanface
[IFNAMSIZ
+ 1];
34 char lan1face
[IFNAMSIZ
+ 1];
35 char lan2face
[IFNAMSIZ
+ 1];
36 char lan3face
[IFNAMSIZ
+ 1];
38 char wan6face
[IFNAMSIZ
+ 1];
40 char lan_cclass
[sizeof("xxx.xxx.xxx.") + 1];
43 static int debug_only
= 0;
46 static int gateway_mode
;
47 static int remotemanage
;
50 const char *chain_in_drop
;
51 const char *chain_in_accept
;
52 const char *chain_out_drop
;
53 const char *chain_out_accept
;
54 const char *chain_out_reject
;
56 const char chain_wan_prerouting
[] = "WANPREROUTING";
57 const char ipt_fname
[] = "/etc/iptables";
61 const char ip6t_fname
[] = "/etc/ip6tables";
71 // -----------------------------------------------------------------------------
74 void enable_ip_forward(void)
78 0 - disabled (default)
81 Forward Packets between interfaces.
83 This variable is special, its change resets all configuration
84 parameters to their default state (RFC1122 for hosts, RFC1812
87 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
91 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "1", 0, 0);
92 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "1", 0, 0);
98 // -----------------------------------------------------------------------------
101 static int ip2cclass(char *ipaddr, char *new, int count)
105 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
106 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
111 static int dmz_dst(char *s
)
117 if (nvram_get_int("dmz_enable") <= 0) return 0;
119 p
= nvram_safe_get("dmz_ipaddr");
120 if ((ia
.s_addr
= inet_addr(p
)) == (in_addr_t
)-1) {
121 if (((n
= atoi(p
)) <= 0) || (n
>= 255)) return 0;
122 if (s
) sprintf(s
, "%s%d", lan_cclass
, n
);
126 if (s
) strcpy(s
, inet_ntoa(ia
));
130 int ipt_addr(char *addr
, int maxlen
, const char *s
, const char *dir
, int family
,
131 const char *categ
, const char *name
)
133 char p
[INET6_ADDRSTRLEN
* 2];
136 if ((s
) && (*s
) && (*dir
))
138 if (sscanf(s
, "%[0-9.]-%[0-9.]", p
, p
) == 2) {
139 snprintf(addr
, maxlen
, "-m iprange --%s-range %s", dir
, s
);
140 r
= (family
== AF_INET
);
143 else if (sscanf(s
, "%[0-9A-Fa-f:]-%[0-9A-Fa-f:]", p
, p
) == 2) {
144 snprintf(addr
, maxlen
, "-m iprange --%s-range %s", dir
, s
);
145 r
= (family
== AF_INET6
);
149 snprintf(addr
, maxlen
, "-%c %s", dir
[0], s
);
150 r
= (host_to_addr(s
, family
) != NULL
);
156 if (r
== 0 && (categ
&& *categ
)) {
158 "IPv%d firewall: %s: not using %s%s%s (could not resolve as valid IPv%d address)",
159 (family
== AF_INET6
) ? 6 : 4, categ
, s
,
160 (name
&& *name
) ? " for " : "", (name
&& *name
) ? name
: "",
161 (family
== AF_INET6
) ? 6 : 4);
167 #define ipt_source(s, src, categ, name) ipt_addr(src, 64, s, "src", AF_INET, categ, name)
168 #define ip6t_source(s, src, categ, name) ipt_addr(src, 128, s, "src", AF_INET6, categ, name)
171 static void get_src(const char *nv, char *src)
175 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
176 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
184 void ipt_write(const char *format
, ...)
188 va_start(args
, format
);
189 vfprintf(ipt_file
, format
, args
);
193 void ip6t_write(const char *format
, ...)
198 va_start(args
, format
);
199 vfprintf(ip6t_file
, format
, args
);
204 // -----------------------------------------------------------------------------
206 int ipt_dscp(const char *v
, char *opt
)
215 n
= strtoul(v
, NULL
, 0);
217 sprintf(opt
, " -m dscp --dscp 0x%02X", n
);
222 modprobe("ipt_dscp");
227 // -----------------------------------------------------------------------------
230 int ipt_ipp2p(const char *v
, char *opt
)
239 strcpy(opt
, "-m ipp2p ");
240 if ((n
& 0xFFF) == 0xFFF) {
241 strcat(opt
, "--ipp2p");
245 if (n
& 0x0001) strcat(opt
, "--apple ");
246 if (n
& 0x0002) strcat(opt
, "--ares ");
247 if (n
& 0x0004) strcat(opt
, "--bit ");
248 if (n
& 0x0008) strcat(opt
, "--dc ");
249 if (n
& 0x0010) strcat(opt
, "--edk ");
250 if (n
& 0x0020) strcat(opt
, "--gnu ");
251 if (n
& 0x0040) strcat(opt
, "--kazaa ");
252 if (n
& 0x0080) strcat(opt
, "--mute ");
253 if (n
& 0x0100) strcat(opt
, "--soul ");
254 if (n
& 0x0200) strcat(opt
, "--waste ");
255 if (n
& 0x0400) strcat(opt
, "--winmx ");
256 if (n
& 0x0800) strcat(opt
, "--xdcc ");
259 modprobe("ipt_ipp2p");
264 // -----------------------------------------------------------------------------
269 // This L7 matches inbound traffic, caches the results, then the L7 outbound
270 // should read the cached result and set the appropriate marks -- zzz
271 void ipt_layer7_inbound(void)
276 if (!layer7_in
) return;
278 en
= nvram_match("nf_l7in", "1");
280 ipt_write(":L7in - [0:0]\n");
281 for (i
= 0; i
< wanfaces
.count
; ++i
) {
282 if (*(wanfaces
.iface
[i
].name
)) {
283 ipt_write("-A FORWARD -i %s -j L7in\n",
284 wanfaces
.iface
[i
].name
);
291 if (en
) ipt_write("-A L7in %s -j RETURN\n", *p
);
299 int ipt_layer7(const char *v
, char *opt
)
305 if (*v
== 0) return 0;
306 if (strlen(v
) > 32) return -1;
308 path
= "/etc/l7-extra";
309 sprintf(s
, "%s/%s.pat", path
, v
);
311 path
= "/etc/l7-protocols";
312 sprintf(s
, "%s/%s.pat", path
, v
);
314 syslog(LOG_ERR
, "L7 %s was not found", v
);
319 sprintf(opt
, "-m layer7 --l7dir %s --l7proto %s", path
, v
);
321 if (nvram_match("nf_l7in", "1")) {
322 if (!layer7_in
) layer7_in
= calloc(51, sizeof(char *));
328 if (strcmp(*p
, opt
) == 0) return 1;
331 if (((p
- layer7_in
) / sizeof(char *)) < 50) *p
= strdup(opt
);
336 modprobe("xt_layer7");
338 modprobe("ipt_layer7");
343 // -----------------------------------------------------------------------------
345 static void ipt_account(void) {
346 struct in_addr ipaddr
, netmask
, network
;
347 char lanN_ifname
[] = "lanXX_ifname";
348 char lanN_ipaddr
[] = "lanXX_ipaddr";
349 char lanN_netmask
[] = "lanXX_netmask";
350 char lanN
[] = "lanXX";
351 char netaddrnetmask
[] = "255.255.255.255/255.255.255.255 ";
354 for(br
=0 ; br
<=3 ; br
++) {
355 char bridge
[2] = "0";
361 sprintf(lanN_ifname
, "lan%s_ifname", bridge
);
363 if (strcmp(nvram_safe_get(lanN_ifname
), "")!=0) {
365 sprintf(lanN_ipaddr
, "lan%s_ipaddr", bridge
);
366 sprintf(lanN_netmask
, "lan%s_netmask", bridge
);
367 sprintf(lanN
, "lan%s", bridge
);
369 inet_aton(nvram_safe_get(lanN_ipaddr
), &ipaddr
);
370 inet_aton(nvram_safe_get(lanN_netmask
), &netmask
);
372 // bitwise AND of ip and netmask gives the network
373 network
.s_addr
= ipaddr
.s_addr
& netmask
.s_addr
;
375 sprintf(netaddrnetmask
, "%s/%s", inet_ntoa(network
), nvram_safe_get(lanN_netmask
));
377 ipt_write("-A FORWARD -m account --aaddr %s --aname %s\n", netaddrnetmask
, lanN
);
382 // -----------------------------------------------------------------------------
384 static void save_webmon(void)
386 system("cp /proc/webmon_recent_domains /var/webmon/domain");
387 system("cp /proc/webmon_recent_searches /var/webmon/search");
390 static void ipt_webmon(int do_ip6t
)
392 int wmtype
, clear
, i
;
397 if (!nvram_get_int("log_wm")) return;
398 wmtype
= nvram_get_int("log_wmtype");
399 clear
= nvram_get_int("log_wmclear");
401 ip46t_cond_write(do_ip6t
, ":monitor - [0:0]\n");
404 strlcpy(t
, wmtype
== 1 ? nvram_safe_get("log_wmip") : "", sizeof(t
));
407 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
409 if (ipt_addr(src
, sizeof(src
), p
, "src", do_ip6t
? AF_INET6
: AF_INET
, "webmon", "filtering")) {
413 ip6t_write("-A FORWARD -o %s %s -j monitor\n", wan6face
, src
);
417 for (i
= 0; i
< wanfaces
.count
; ++i
) {
418 if (*(wanfaces
.iface
[i
].name
)) {
419 ipt_write("-A FORWARD -o %s %s -j monitor\n",
420 wanfaces
.iface
[i
].name
, src
);
431 strlcpy(t
, nvram_safe_get("log_wmip"), sizeof(t
));
434 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
435 if (ipt_addr(src
, sizeof(src
), p
, "src", do_ip6t
? AF_INET6
: AF_INET
, "webmon", "filtering")) {
437 ip46t_cond_write(do_ip6t
, "-A monitor %s -j RETURN\n", src
);
444 ip46t_cond_write(do_ip6t
,
445 "-A monitor -p tcp -m webmon "
446 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
447 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
448 (clear
& 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
449 (clear
& 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
452 modprobe("xt_webmon");
454 modprobe("ipt_webmon");
459 // -----------------------------------------------------------------------------
461 // -----------------------------------------------------------------------------
463 static void mangle_table(void)
470 ":PREROUTING ACCEPT [0:0]\n"
471 ":OUTPUT ACCEPT [0:0]\n");
477 p
= nvram_safe_get("nf_ttl");
478 if (strncmp(p
, "c:", 2) == 0) {
481 p
= (ttl
>= 0 && ttl
<= 255) ? "set" : NULL
;
483 else if ((ttl
= atoi(p
)) != 0) {
491 if (ttl
> 255) p
= NULL
;
501 // set TTL on primary WAN iface only
502 wanface
= wanfaces
.iface
[0].name
;
504 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
505 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
511 ip46t_write("COMMIT\n");
516 // -----------------------------------------------------------------------------
518 // -----------------------------------------------------------------------------
520 static void nat_table(void)
537 ":PREROUTING ACCEPT [0:0]\n"
538 ":POSTROUTING ACCEPT [0:0]\n"
539 ":OUTPUT ACCEPT [0:0]\n"
541 chain_wan_prerouting
);
544 strlcpy(lanaddr
, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr
));
545 strlcpy(lanmask
, nvram_safe_get("lan_netmask"), sizeof(lanmask
));
546 strlcpy(lan1addr
, nvram_safe_get("lan1_ipaddr"), sizeof(lan1addr
));
547 strlcpy(lan1mask
, nvram_safe_get("lan1_netmask"), sizeof(lan1mask
));
548 strlcpy(lan2addr
, nvram_safe_get("lan2_ipaddr"), sizeof(lan2addr
));
549 strlcpy(lan2mask
, nvram_safe_get("lan2_netmask"), sizeof(lan2mask
));
550 strlcpy(lan3addr
, nvram_safe_get("lan3_ipaddr"), sizeof(lan3addr
));
551 strlcpy(lan3mask
, nvram_safe_get("lan3_netmask"), sizeof(lan3mask
));
554 for (i
= 0; i
< wanfaces
.count
; ++i
) {
555 if (*(wanfaces
.iface
[i
].name
)) {
556 // chain_wan_prerouting
558 ipt_write("-A PREROUTING -d %s -j %s\n",
559 wanfaces
.iface
[i
].ip
, chain_wan_prerouting
);
561 // Drop incoming packets which destination IP address is to our LAN side directly
562 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
563 wanfaces
.iface
[i
].name
,
564 lanaddr
, lanmask
); // note: ipt will correct lanaddr
565 if(strcmp(lan1addr
,"")!=0)
566 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
567 wanfaces
.iface
[i
].name
,
569 if(strcmp(lan2addr
,"")!=0)
570 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
571 wanfaces
.iface
[i
].name
,
573 if(strcmp(lan3addr
,"")!=0)
574 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
575 wanfaces
.iface
[i
].name
,
581 if (nvram_match("dns_intcpt", "1")) {
582 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
586 if(strcmp(lan1addr
,"")!=0)
587 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
591 if(strcmp(lan2addr
,"")!=0)
592 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
596 if(strcmp(lan3addr
,"")!=0)
597 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
603 // ICMP packets are always redirected to INPUT chains
604 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting
, lanaddr
);
606 ipt_forward(IPT_TABLE_NAT
);
607 ipt_triggered(IPT_TABLE_NAT
);
610 if (nvram_get_int("upnp_enable") & 3) {
611 ipt_write(":upnp - [0:0]\n");
613 // ! for loopback (all) to work
614 ipt_write("-A %s -j upnp\n", chain_wan_prerouting
);
617 for (i
= 0; i
< wanfaces
.count
; ++i
) {
618 if (*(wanfaces
.iface
[i
].name
)) {
619 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces
.iface
[i
].name
);
627 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
630 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
631 if (ipt_source(p
, src
, "dmz", NULL
))
632 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting
, src
, dst
);
641 switch (get_ipv6_service()) {
643 // avoid NATing proto-41 packets when using 6in4 tunnel
649 for (i
= 0; i
< wanfaces
.count
; ++i
) {
650 if (*(wanfaces
.iface
[i
].name
)) {
651 if ((!wanup
) || (nvram_get_int("net_snat") != 1))
652 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p
, wanfaces
.iface
[i
].name
);
654 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p
, wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].ip
);
658 switch (nvram_get_int("nf_loopback")) {
659 case 1: // 1 = forwarded-only
660 case 2: // 2 = disable
662 default: // 0 = all (same as block_loopback=0)
663 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
668 if (strcmp(lan1face
,"")!=0)
669 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
674 if (strcmp(lan2face
,"")!=0)
675 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
680 if (strcmp(lan3face
,"")!=0)
681 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
689 ipt_write("COMMIT\n");
692 // -----------------------------------------------------------------------------
694 // -----------------------------------------------------------------------------
696 static void filter_input(void)
706 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
707 for (n
= 0; n
< wanfaces
.count
; ++n
) {
708 if (*(wanfaces
.iface
[n
].name
)) {
709 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanfaces
.iface
[n
].ip
);
710 if (strcmp(lan1face
,"")!=0)
711 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan1face
, wanfaces
.iface
[n
].ip
);
712 if (strcmp(lan2face
,"")!=0)
713 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan2face
, wanfaces
.iface
[n
].ip
);
714 if (strcmp(lan3face
,"")!=0)
715 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lan3face
, wanfaces
.iface
[n
].ip
);
721 "-A INPUT -m state --state INVALID -j %s\n"
722 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
726 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
727 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
729 ? what if the user uses the start button in GUI ?
730 if (nvram_get_int("telnetd_eas"))
731 if (nvram_get_int("sshd_eas"))
734 modprobe("xt_recent");
736 modprobe("ipt_recent");
741 "-A shlimit -m recent --set --name shlimit\n"
742 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
743 atoi(hit
) + 1, sec
, chain_in_drop
);
746 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
747 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
748 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
751 if (n
& 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
755 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
756 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
758 modprobe("xt_recent");
760 modprobe("ipt_recent");
765 "-A ftplimit -m recent --set --name ftp\n"
766 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
767 atoi(hit
) + 1, sec
, chain_in_drop
);
768 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
773 "-A INPUT -i lo -j ACCEPT\n"
774 "-A INPUT -i %s -j ACCEPT\n",
776 if (strcmp(lan1face
,"")!=0)
778 "-A INPUT -i %s -j ACCEPT\n",
780 if (strcmp(lan2face
,"")!=0)
782 "-A INPUT -i %s -j ACCEPT\n",
784 if (strcmp(lan3face
,"")!=0)
786 "-A INPUT -i %s -j ACCEPT\n",
790 switch (get_ipv6_service()) {
792 // Accept ICMP requests from the remote tunnel endpoint
793 if ((p
= nvram_get("ipv6_tun_v4end")) && *p
&& strcmp(p
, "0.0.0.0") != 0)
794 ipt_write("-A INPUT -p icmp -s %s -j %s\n", p
, chain_in_accept
);
795 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept
);
800 // ICMP request from WAN interface
801 if (nvram_match("block_wan", "0")) {
802 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
803 ipt_write("-A INPUT -p icmp -m limit --limit 1/second -j %s\n", chain_in_accept
);
804 // allow udp traceroute packets
805 ipt_write("-A INPUT -p udp -m udp --dport 33434:33534 -m limit --limit 5/second -j %s\n", chain_in_accept
);
808 /* Accept incoming packets from broken dhcp servers, which are sending replies
809 * from addresses other than used for query. This could lead to a lower level
810 * of security, so allow to disable it via nvram variable.
812 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
813 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept
);
816 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
819 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
821 if (ipt_source(p
, s
, "remote management", NULL
)) {
824 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
825 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
828 if (nvram_get_int("sshd_remote")) {
829 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
830 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
838 #ifdef TCONFIG_FTP // !!TB - FTP Server
839 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
840 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
843 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
844 if (ipt_source(p
, s
, "ftp", "remote access")) {
845 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
846 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
854 // IGMP query from WAN interface
855 if (nvram_match("multicast_pass", "1")) {
856 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
857 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
860 // Routing protocol, RIP, accept
861 if (nvram_invmatch("dr_wan_rx", "0")) {
862 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
866 if (*chain_in_drop
== 'l') {
867 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
870 // default policy: DROP
873 // clamp TCP MSS to PMTU of WAN interface
874 static void clampmss(void)
877 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
879 int rmtu
= nvram_get_int("wan_run_mtu");
880 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
882 ipt_write("--clamp-mss-to-pmtu\n");
885 ipt_write("--set-mss %d\n", rmtu
- 40);
890 static void filter_forward(void)
898 if (nvram_match("cstats_enable", "1")) {
903 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
905 if (strcmp(lan1face
,"")!=0)
907 "-A FORWARD -i %s -o %s -j ACCEPT\n",
909 if (strcmp(lan2face
,"")!=0)
911 "-A FORWARD -i %s -o %s -j ACCEPT\n",
913 if (strcmp(lan3face
,"")!=0)
915 "-A FORWARD -i %s -o %s -j ACCEPT\n",
918 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
920 // clamp tcp mss to pmtu
925 ipt_layer7_inbound();
933 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
935 for (i
= 0; i
< wanfaces
.count
; ++i
) {
936 if (*(wanfaces
.iface
[i
].name
)) {
938 "-A FORWARD -i %s -j wanin\n" // generic from wan
939 "-A FORWARD -o %s -j wanout\n", // generic to wan
940 wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].name
);
944 for (i
= 0; i
< wanfaces
.count
; ++i
) {
945 if (*(wanfaces
.iface
[i
].name
)) {
946 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lanface
, wanfaces
.iface
[i
].name
, chain_out_accept
);
947 if (strcmp(lan1face
,"")!=0)
948 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan1face
, wanfaces
.iface
[i
].name
, chain_out_accept
);
949 if (strcmp(lan2face
,"")!=0)
950 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan2face
, wanfaces
.iface
[i
].name
, chain_out_accept
);
951 if (strcmp(lan3face
,"")!=0)
952 ipt_write("-A FORWARD -i %s -o %s -j %s\n", lan3face
, wanfaces
.iface
[i
].name
, chain_out_accept
);
956 const char *d
, *sbr
, *saddr
, *dbr
, *daddr
, *desc
;
959 nvp
= nv
= strdup(nvram_safe_get("lan_access"));
961 while ((b
= strsep(&nvp
, ">")) != NULL
) {
963 1<0<1.2.3.4<1<5.6.7.8<30,45-50<desc
972 n
= vstrsep(b
, "<", &d
, &sbr
, &saddr
, &dbr
, &daddr
, &desc
);
975 if (!ipt_addr(src
, sizeof(src
), saddr
, "src", AF_INET
, "LAN access", desc
))
977 if (!ipt_addr(dst
, sizeof(dst
), daddr
, "dst", AF_INET
, "LAN access", desc
))
980 ipt_write("-A FORWARD -i %s%s -o %s%s %s %s -j ACCEPT\n",
991 if (nvram_get_int("upnp_enable") & 3) {
992 ipt_write(":upnp - [0:0]\n");
993 for (i
= 0; i
< wanfaces
.count
; ++i
) {
994 if (*(wanfaces
.iface
[i
].name
)) {
995 ipt_write("-A FORWARD -i %s -j upnp\n",
996 wanfaces
.iface
[i
].name
);
1002 if (nvram_match("multicast_pass", "1")) {
1003 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
1005 ipt_triggered(IPT_TABLE_FILTER
);
1006 ipt_forward(IPT_TABLE_FILTER
);
1009 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
1012 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1013 if (ipt_source(p
, src
, "dmz", NULL
))
1014 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
1021 // default policy: DROP
1024 static void filter_log(void)
1029 n
= nvram_get_int("log_limit");
1030 if ((n
>= 1) && (n
<= 9999)) {
1031 sprintf(limit
, "-m limit --limit %d/m", n
);
1038 modprobe("ip6t_LOG");
1040 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
1042 ":logdrop - [0:0]\n"
1043 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
1044 "-A logdrop -j DROP\n"
1045 ":logreject - [0:0]\n"
1046 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
1047 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1050 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
1052 ":logaccept - [0:0]\n"
1053 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
1054 "-A logaccept -j ACCEPT\n",
1060 static void filter6_input(void)
1071 "-A INPUT -m rt --rt-type 0 -j %s\n"
1072 /* "-A INPUT -m state --state INVALID -j %s\n" */
1073 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1074 chain_in_drop
/*, chain_in_drop*/);
1077 modprobe("xt_length");
1078 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1081 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
1082 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
1084 modprobe("xt_recent");
1086 modprobe("ipt_recent");
1091 "-A shlimit -m recent --set --name shlimit\n"
1092 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1093 atoi(hit
) + 1, sec
, chain_in_drop
);
1096 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface
, nvram_safe_get("sshd_port"));
1097 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1098 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1101 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"));
1105 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
1106 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
1108 modprobe("xt_recent");
1110 modprobe("ipt_recent");
1115 "-A ftplimit -m recent --set --name ftp\n"
1116 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1117 atoi(hit
) + 1, sec
, chain_in_drop
);
1118 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1120 #endif // TCONFIG_FTP
1123 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1124 "-A INPUT -i lo -j ACCEPT\n",
1127 switch (get_ipv6_service()) {
1128 case IPV6_NATIVE_DHCP
:
1129 // allow responses from the dhcpv6 server
1130 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept
);
1135 const int allowed_icmpv6
[6] = { 1, 2, 3, 4, 128, 129 };
1136 for (n
= 0; n
< sizeof(allowed_icmpv6
)/sizeof(int); n
++) {
1137 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[n
], chain_in_accept
);
1141 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
1144 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1146 if (ip6t_source(p
, s
, "remote management", NULL
)) {
1149 ip6t_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
1150 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
1153 if (nvram_get_int("sshd_remote")) {
1154 ip6t_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
1155 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
1165 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1166 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
1169 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1170 if (ip6t_source(p
, s
, "ftp", "remote access")) {
1171 ip6t_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
1172 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
1181 if (*chain_in_drop
== 'l') {
1182 ip6t_write( "-A INPUT -j %s\n", chain_in_drop
);
1185 // default policy: DROP
1188 static void filter6_forward(void)
1193 "-A FORWARD -m rt --rt-type 0 -j DROP\n"
1194 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
1195 /*"-A FORWARD -m state --state INVALID -j DROP\n"*/, // drop if INVALID state
1198 // Filter out invalid WAN->WAN connections
1200 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face
, lanface
, chain_in_drop
);
1203 modprobe("xt_length");
1204 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1207 // clamp tcp mss to pmtu TODO?
1210 // TODO: support l7, access restrictions on ipv6?
1214 ipt_layer7_inbound();
1224 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
1228 "-A FORWARD -i %s -j wanin\n" // generic from wan
1229 "-A FORWARD -o %s -j wanout\n", // generic to wan
1230 wan6face
, wan6face
);
1234 "-A FORWARD -i %s -j %s\n", // from lan
1235 lanface
, chain_out_accept
);
1238 const int allowed_icmpv6
[6] = { 1, 2, 3, 4, 128, 129 };
1239 for (n
= 0; n
< sizeof(allowed_icmpv6
)/sizeof(int); n
++) {
1240 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[n
], chain_in_accept
);
1244 //ipt_triggered(IPT_TABLE_FILTER);
1248 // default policy: DROP
1253 static void filter_table(void)
1257 ":INPUT DROP [0:0]\n"
1258 ":OUTPUT ACCEPT [0:0]\n"
1266 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop
);
1269 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
1270 ip46t_write(":FORWARD DROP [0:0]\n");
1277 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1280 ip46t_write("COMMIT\n");
1283 // -----------------------------------------------------------------------------
1285 int start_firewall(void)
1288 struct dirent
*dirent
;
1293 char *iptrestore_argv
[] = { "iptables-restore", (char *)ipt_fname
, NULL
};
1295 char *ip6trestore_argv
[] = { "ip6tables-restore", (char *)ip6t_fname
, NULL
};
1298 simple_lock("firewall");
1299 simple_lock("restrictions");
1301 wanproto
= get_wan_proto();
1302 wanup
= check_wanup();
1304 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1306 /* NAT performance tweaks
1307 * These values can be overriden later if needed via firewall script
1309 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1310 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1311 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1312 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1313 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1314 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1315 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1316 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1317 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1318 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1319 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1320 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1322 /* DoS-related tweaks */
1323 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1324 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1325 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1328 /* Force IGMPv2 due EMF limitations */
1329 if (nvram_get_int("emf_enable")) {
1330 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1331 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1335 n
= nvram_get_int("log_in");
1336 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
1337 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1339 n
= nvram_get_int("log_out");
1340 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
1341 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1342 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1344 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1346 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
1347 strlcpy(lan1face
, nvram_safe_get("lan1_ifname"), IFNAMSIZ
);
1348 strlcpy(lan2face
, nvram_safe_get("lan2_ifname"), IFNAMSIZ
);
1349 strlcpy(lan3face
, nvram_safe_get("lan3_ifname"), IFNAMSIZ
);
1351 memcpy(&wanfaces
, get_wanfaces(), sizeof(wanfaces
));
1352 wanface
= wanfaces
.iface
[0].name
;
1354 strlcpy(wan6face
, get_wan6face(), sizeof(wan6face
));
1357 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
1358 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
1359 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
1361 strlcpy(s, nvram_safe_get("lan1_ipaddr"), sizeof(s));
1362 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1363 strlcpy(lan1_cclass, s, sizeof(lan1_cclass));
1365 strlcpy(s, nvram_safe_get("lan2_ipaddr"), sizeof(s));
1366 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1367 strlcpy(lan2_cclass, s, sizeof(lan2_cclass));
1369 strlcpy(s, nvram_safe_get("lan3_ipaddr"), sizeof(s));
1370 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1371 strlcpy(lan3_cclass, s, sizeof(lan3_cclass));
1375 block obviously spoofed IP addresses
1378 1 - do source validation by reversed path, as specified in RFC1812
1379 Recommended option for single homed hosts and stub network
1380 routers. Could cause troubles for complicated (not loop free)
1381 networks running a slow unreliable protocol (sort of RIP),
1382 or using static routes.
1383 0 - No source validation.
1385 c
= nvram_get("wan_ifname");
1386 /* mcast needs rp filter to be turned off only for non default iface */
1387 if (!(nvram_match("multicast_pass", "1")) || strcmp(wanface
, c
) == 0) c
= NULL
;
1389 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
1390 while ((dirent
= readdir(dir
)) != NULL
) {
1391 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
1392 f_write_string(s
, (c
&& strcmp(dirent
->d_name
, c
) == 0) ? "0" : "1", 0, 0);
1398 gateway_mode
= !nvram_match("wk_mode", "router");
1400 /* Remote management */
1401 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1402 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
1405 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
1406 notice_set("iptables", "Unable to create iptables restore file");
1407 simple_unlock("firewall");
1412 if ((ip6t_file
= fopen(ip6t_fname
, "w")) == NULL
) {
1413 notice_set("ip6tables", "Unable to create ip6tables restore file");
1414 simple_unlock("firewall");
1417 modprobe("nf_conntrack_ipv6");
1418 modprobe("ip6t_REJECT");
1433 #ifdef DEBUG_IPTFILE
1435 simple_unlock("firewall");
1436 simple_unlock("restrictions");
1443 if (nvram_get_int("upnp_enable") & 3) {
1444 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
1445 if (killall("miniupnpd", SIGUSR2
) == 0) {
1446 f_wait_notexists("/etc/upnp/save", 5);
1450 notice_set("iptables", "");
1451 if (_eval(iptrestore_argv
, ">/var/notice/iptables", 0, NULL
) == 0) {
1453 notice_set("iptables", "");
1456 sprintf(s
, "%s.error", ipt_fname
);
1457 rename(ipt_fname
, s
);
1458 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1465 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1466 -A INPUT -i br0 -j ACCEPT
1470 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1471 -A FORWARD -i br0 -j ACCEPT
1477 if (ipv6_enabled()) {
1478 notice_set("ip6tables", "");
1479 if (_eval(ip6trestore_argv
, ">/var/notice/ip6tables", 0, NULL
) == 0) {
1480 notice_set("ip6tables", "");
1483 sprintf(s
, "%s.error", ip6t_fname
);
1484 rename(ip6t_fname
, s
);
1485 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1491 if (nvram_get_int("upnp_enable") & 3) {
1492 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
1493 killall("miniupnpd", SIGUSR2
);
1496 simple_unlock("restrictions");
1497 sched_restrictions();
1498 enable_ip_forward();
1500 led(LED_DMZ
, dmz_dst(NULL
));
1503 modprobe_r("nf_conntrack_ipv6");
1504 modprobe_r("ip6t_LOG");
1505 modprobe_r("ip6t_REJECT");
1508 modprobe_r("xt_layer7");
1509 modprobe_r("xt_recent");
1510 modprobe_r("xt_HL");
1511 modprobe_r("xt_length");
1512 modprobe_r("xt_web");
1513 modprobe_r("xt_webmon");
1514 modprobe_r("xt_dscp");
1516 modprobe_r("ipt_layer7");
1517 modprobe_r("ipt_recent");
1518 modprobe_r("ipt_TTL");
1519 modprobe_r("ipt_web");
1520 modprobe_r("ipt_webmon");
1521 modprobe_r("ipt_dscp");
1523 modprobe_r("ipt_ipp2p");
1525 unlink("/var/webmon/domain");
1526 unlink("/var/webmon/search");
1528 #ifdef TCONFIG_OPENVPN
1529 run_vpn_firewall_scripts();
1531 run_nvscript("script_fire", NULL
, 1);
1533 simple_unlock("firewall");
1537 int stop_firewall(void)
1543 #ifdef DEBUG_IPTFILE
1544 void create_test_iptfile(void)