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];
35 char wan6face
[IFNAMSIZ
+ 1];
37 char lan_cclass
[sizeof("xxx.xxx.xxx.") + 1];
39 static int can_enable_fastnat
;
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";
64 // RFC-4890, sec. 4.3.1
65 const int allowed_icmpv6
[] = { 1, 2, 3, 4, 128, 129 };
74 // -----------------------------------------------------------------------------
77 void enable_fastnat(int enable
)
79 f_write_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_fastnat",
80 enable
? "1" : "0", 0, 0);
83 int fastnat_enabled(void)
87 if (f_read_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_fastnat", v
, sizeof(v
)) > 0)
94 void enable_ip_forward(void)
98 0 - disabled (default)
101 Forward Packets between interfaces.
103 This variable is special, its change resets all configuration
104 parameters to their default state (RFC1122 for hosts, RFC1812
107 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
110 if (ipv6_enabled()) {
111 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "1", 0, 0);
112 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "1", 0, 0);
118 // -----------------------------------------------------------------------------
121 static int ip2cclass(char *ipaddr, char *new, int count)
125 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
126 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
131 static int dmz_dst(char *s
)
137 if (nvram_get_int("dmz_enable") <= 0) return 0;
139 p
= nvram_safe_get("dmz_ipaddr");
140 if ((ia
.s_addr
= inet_addr(p
)) == (in_addr_t
)-1) {
141 if (((n
= atoi(p
)) <= 0) || (n
>= 255)) return 0;
142 if (s
) sprintf(s
, "%s%d", lan_cclass
, n
);
146 if (s
) strcpy(s
, inet_ntoa(ia
));
150 void ipt_log_unresolved(const char *addr
, const char *addrtype
, const char *categ
, const char *name
)
154 pre
= (name
&& *name
) ? " for \"" : "";
155 post
= (name
&& *name
) ? "\"" : "";
157 syslog(LOG_WARNING
, "firewall: "
158 "%s: not using %s%s%s%s (could not resolve as valid %s address)",
159 categ
, addr
, pre
, (name
) ? : "", post
, (addrtype
) ? : "IP");
162 int ipt_addr(char *addr
, int maxlen
, const char *s
, const char *dir
, int af
,
163 int strict
, const char *categ
, const char *name
)
165 char p
[INET6_ADDRSTRLEN
* 2];
168 if ((s
) && (*s
) && (*dir
))
170 if (sscanf(s
, "%[0-9.]-%[0-9.]", p
, p
) == 2) {
171 snprintf(addr
, maxlen
, "-m iprange --%s-range %s", dir
, s
);
175 else if (sscanf(s
, "%[0-9A-Fa-f:]-%[0-9A-Fa-f:]", p
, p
) == 2) {
176 snprintf(addr
, maxlen
, "-m iprange --%s-range %s", dir
, s
);
181 snprintf(addr
, maxlen
, "-%c %s", dir
[0], s
);
182 if (sscanf(s
, "%[^/]/", p
)) {
184 r
= host_addrtypes(p
, strict
? af
: (IPT_V4
| IPT_V6
));
186 r
= host_addrtypes(p
, IPT_V4
);
194 r
= (IPT_V4
| IPT_V6
);
197 if ((r
== 0 || (strict
&& ((r
& af
) != af
))) && (categ
&& *categ
)) {
198 ipt_log_unresolved(s
, categ
, name
,
199 (af
& IPT_V4
& ~r
) ? "IPv4" : ((af
& IPT_V6
& ~r
) ? "IPv6" : NULL
));
205 #define ipt_source_strict(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 1, categ, name)
206 #define ipt_source(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 0, categ, name)
207 #define ip6t_source(s, src, categ, name) ipt_addr(src, 128, s, "src", IPT_V6, 0, categ, name)
210 static void get_src(const char *nv, char *src)
214 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
215 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
223 void ipt_write(const char *format
, ...)
227 va_start(args
, format
);
228 vfprintf(ipt_file
, format
, args
);
232 void ip6t_write(const char *format
, ...)
237 va_start(args
, format
);
238 vfprintf(ip6t_file
, format
, args
);
243 // -----------------------------------------------------------------------------
245 int ipt_dscp(const char *v
, char *opt
)
254 n
= strtoul(v
, NULL
, 0);
256 sprintf(opt
, " -m dscp --dscp 0x%02X", n
);
261 modprobe("ipt_dscp");
266 // -----------------------------------------------------------------------------
269 int ipt_ipp2p(const char *v
, char *opt
)
278 strcpy(opt
, "-m ipp2p ");
279 if ((n
& 0xFFF) == 0xFFF) {
280 strcat(opt
, "--ipp2p");
284 if (n
& 0x0001) strcat(opt
, "--apple ");
285 if (n
& 0x0002) strcat(opt
, "--ares ");
286 if (n
& 0x0004) strcat(opt
, "--bit ");
287 if (n
& 0x0008) strcat(opt
, "--dc ");
288 if (n
& 0x0010) strcat(opt
, "--edk ");
289 if (n
& 0x0020) strcat(opt
, "--gnu ");
290 if (n
& 0x0040) strcat(opt
, "--kazaa ");
291 if (n
& 0x0080) strcat(opt
, "--mute ");
292 if (n
& 0x0100) strcat(opt
, "--soul ");
293 if (n
& 0x0200) strcat(opt
, "--waste ");
294 if (n
& 0x0400) strcat(opt
, "--winmx ");
295 if (n
& 0x0800) strcat(opt
, "--xdcc ");
298 modprobe("ipt_ipp2p");
303 // -----------------------------------------------------------------------------
308 // This L7 matches inbound traffic, caches the results, then the L7 outbound
309 // should read the cached result and set the appropriate marks -- zzz
310 void ipt_layer7_inbound(void)
315 if (!layer7_in
) return;
317 en
= nvram_match("nf_l7in", "1");
319 ipt_write(":L7in - [0:0]\n");
320 for (i
= 0; i
< wanfaces
.count
; ++i
) {
321 if (*(wanfaces
.iface
[i
].name
)) {
322 ipt_write("-A FORWARD -i %s -j L7in\n",
323 wanfaces
.iface
[i
].name
);
331 ipt_write("-A L7in %s -j RETURN\n", *p
);
333 can_enable_fastnat
= 0;
343 int ipt_layer7(const char *v
, char *opt
)
349 if (*v
== 0) return 0;
350 if (strlen(v
) > 32) return -1;
352 path
= "/etc/l7-extra";
353 sprintf(s
, "%s/%s.pat", path
, v
);
355 path
= "/etc/l7-protocols";
356 sprintf(s
, "%s/%s.pat", path
, v
);
358 syslog(LOG_ERR
, "L7 %s was not found", v
);
363 sprintf(opt
, "-m layer7 --l7dir %s --l7proto %s", path
, v
);
365 if (nvram_match("nf_l7in", "1")) {
366 if (!layer7_in
) layer7_in
= calloc(51, sizeof(char *));
372 if (strcmp(*p
, opt
) == 0) return 1;
375 if (((p
- layer7_in
) / sizeof(char *)) < 50) *p
= strdup(opt
);
380 modprobe("xt_layer7");
382 modprobe("ipt_layer7");
388 // -----------------------------------------------------------------------------
390 static void save_webmon(void)
392 eval("cp", "/proc/webmon_recent_domains", "/var/webmon/domain");
393 eval("cp", "/proc/webmon_recent_searches", "/var/webmon/search");
396 static void ipt_webmon()
398 int wmtype
, clear
, i
;
404 if (!nvram_get_int("log_wm")) return;
407 can_enable_fastnat
= 0;
409 wmtype
= nvram_get_int("log_wmtype");
410 clear
= nvram_get_int("log_wmclear");
412 ip46t_write(":monitor - [0:0]\n");
415 strlcpy(t
, wmtype
== 1 ? nvram_safe_get("log_wmip") : "", sizeof(t
));
418 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
420 if ((ok
= ipt_addr(src
, sizeof(src
), p
, "src", IPT_V4
|IPT_V6
, 0, "webmon", NULL
))) {
422 if (*wan6face
&& (ok
& IPT_V6
))
423 ip6t_write("-A FORWARD -o %s %s -j monitor\n", wan6face
, src
);
426 for (i
= 0; i
< wanfaces
.count
; ++i
) {
427 if (*(wanfaces
.iface
[i
].name
)) {
428 ipt_write("-A FORWARD -o %s %s -j monitor\n",
429 wanfaces
.iface
[i
].name
, src
);
441 strlcpy(t
, nvram_safe_get("log_wmip"), sizeof(t
));
444 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
445 if ((ok
= ipt_addr(src
, sizeof(src
), p
, "src", IPT_V4
|IPT_V6
, 0, "webmon", NULL
))) {
447 ip46t_flagged_write(ok
, "-A monitor %s -j RETURN\n", src
);
455 "-A monitor -p tcp -m webmon "
456 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
457 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
458 (clear
& 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
459 (clear
& 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
462 modprobe("xt_webmon");
464 modprobe("ipt_webmon");
469 // -----------------------------------------------------------------------------
471 // -----------------------------------------------------------------------------
473 static void mangle_table(void)
480 ":PREROUTING ACCEPT [0:0]\n"
481 ":OUTPUT ACCEPT [0:0]\n");
489 p
= nvram_safe_get("nf_ttl");
490 if (strncmp(p
, "c:", 2) == 0) {
493 p
= (ttl
>= 0 && ttl
<= 255) ? "set" : NULL
;
495 else if ((ttl
= atoi(p
)) != 0) {
503 if (ttl
> 255) p
= NULL
;
513 // set TTL on primary WAN iface only
514 wanface
= wanfaces
.iface
[0].name
;
516 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
517 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
521 // FIXME: IPv6 HL should be configurable separately from TTL.
522 // disable it until GUI setting is implemented.
525 "-I PREROUTING -i %s -j HL --hl-%s %d\n"
526 "-I POSTROUTING -o %s -j HL --hl-%s %d\n",
534 ip46t_write("COMMIT\n");
537 // -----------------------------------------------------------------------------
539 // -----------------------------------------------------------------------------
541 static void nat_table(void)
552 ":PREROUTING ACCEPT [0:0]\n"
553 ":POSTROUTING ACCEPT [0:0]\n"
554 ":OUTPUT ACCEPT [0:0]\n"
556 chain_wan_prerouting
);
562 strlcpy(lanaddr
, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr
));
563 strlcpy(lanmask
, nvram_safe_get("lan_netmask"), sizeof(lanmask
));
565 for (i
= 0; i
< wanfaces
.count
; ++i
) {
566 if (*(wanfaces
.iface
[i
].name
)) {
567 // Drop incoming packets which destination IP address is to our LAN side directly
568 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
569 wanfaces
.iface
[i
].name
,
570 lanaddr
, lanmask
); // note: ipt will correct lanaddr
572 // chain_wan_prerouting
574 ipt_write("-A PREROUTING -d %s -j %s\n",
575 wanfaces
.iface
[i
].ip
, chain_wan_prerouting
);
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",
588 // ICMP packets are always redirected to INPUT chains
589 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting
, lanaddr
);
591 ipt_forward(IPT_TABLE_NAT
);
592 ipt_triggered(IPT_TABLE_NAT
);
595 if (nvram_get_int("upnp_enable") & 3) {
596 ipt_write(":upnp - [0:0]\n");
598 for (i
= 0; i
< wanfaces
.count
; ++i
) {
599 if (*(wanfaces
.iface
[i
].name
)) {
601 // ! for loopback (all) to work
602 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces
.iface
[i
].ip
);
605 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces
.iface
[i
].name
);
613 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
616 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
617 if (ipt_source_strict(p
, src
, "dmz", NULL
))
618 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting
, src
, dst
);
627 switch (get_ipv6_service()) {
629 // avoid NATing proto-41 packets when using 6in4 tunnel
635 for (i
= 0; i
< wanfaces
.count
; ++i
) {
636 if (*(wanfaces
.iface
[i
].name
)) {
637 if ((!wanup
) || (nvram_get_int("net_snat") != 1))
638 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p
, wanfaces
.iface
[i
].name
);
640 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p
, wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].ip
);
644 switch (nvram_get_int("nf_loopback")) {
645 case 1: // 1 = forwarded-only
646 case 2: // 2 = disable
648 default: // 0 = all (same as block_loopback=0)
649 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
657 ipt_write("COMMIT\n");
660 // -----------------------------------------------------------------------------
662 // -----------------------------------------------------------------------------
664 static void filter_input(void)
674 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
675 for (n
= 0; n
< wanfaces
.count
; ++n
) {
676 if (*(wanfaces
.iface
[n
].name
)) {
677 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanfaces
.iface
[n
].ip
);
683 "-A INPUT -m state --state INVALID -j DROP\n"
684 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
686 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
687 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
689 ? what if the user uses the start button in GUI ?
690 if (nvram_get_int("telnetd_eas"))
691 if (nvram_get_int("sshd_eas"))
694 modprobe("xt_recent");
696 modprobe("ipt_recent");
701 "-A shlimit -m recent --set --name shlimit\n"
702 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
703 atoi(hit
) + 1, sec
, chain_in_drop
);
706 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
707 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
708 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
711 if (n
& 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
715 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
716 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
718 modprobe("xt_recent");
720 modprobe("ipt_recent");
725 "-A ftplimit -m recent --set --name ftp\n"
726 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
727 atoi(hit
) + 1, sec
, chain_in_drop
);
728 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
733 "-A INPUT -i %s -j ACCEPT\n"
734 "-A INPUT -i lo -j ACCEPT\n",
738 n
= get_ipv6_service();
740 case IPV6_ANYCAST_6TO4
:
742 // Accept ICMP requests from the remote tunnel endpoint
743 if (n
== IPV6_ANYCAST_6TO4
)
744 sprintf(s
, "192.88.99.%d", nvram_get_int("ipv6_relay"));
746 strlcpy(s
, nvram_safe_get("ipv6_tun_v4end"), sizeof(s
));
747 if (*s
&& strcmp(s
, "0.0.0.0") != 0)
748 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s
, chain_in_accept
);
749 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept
);
754 // ICMP request from WAN interface
755 if (nvram_match("block_wan", "0")) {
756 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
757 ipt_write("-A INPUT -p icmp -m limit --limit 1/second -j %s\n", chain_in_accept
);
758 // allow udp traceroute packets
759 ipt_write("-A INPUT -p udp -m udp --dport 33434:33534 -m limit --limit 5/second -j %s\n", chain_in_accept
);
762 /* Accept incoming packets from broken dhcp servers, which are sending replies
763 * from addresses other than used for query. This could lead to a lower level
764 * of security, so allow to disable it via nvram variable.
766 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
767 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept
);
770 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
773 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
775 if (ipt_source(p
, s
, "remote management", NULL
)) {
778 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
779 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
782 if (nvram_get_int("sshd_remote")) {
783 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
784 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
792 #ifdef TCONFIG_FTP // !!TB - FTP Server
793 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
794 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
797 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
798 if (ipt_source(p
, s
, "ftp", "remote access")) {
799 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
800 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
808 // IGMP query from WAN interface
809 if (nvram_match("multicast_pass", "1")) {
810 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
811 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
814 // Routing protocol, RIP, accept
815 if (nvram_invmatch("dr_wan_rx", "0")) {
816 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
820 if (*chain_in_drop
== 'l') {
821 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
824 // default policy: DROP
827 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
828 static void clampmss(void)
831 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
833 int rmtu
= nvram_get_int("wan_run_mtu");
834 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
836 ipt_write("--clamp-mss-to-pmtu\n");
839 ipt_write("--set-mss %d\n", rmtu
- 40);
844 static void filter_forward(void)
854 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
858 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
863 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
865 // clamp tcp mss to pmtu
871 ipt_layer7_inbound();
879 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
882 // Filter out invalid WAN->WAN connections
884 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face
, lanface
, chain_in_drop
);
887 modprobe("xt_length");
888 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
892 for (i
= 0; i
< sizeof(allowed_icmpv6
)/sizeof(int); ++i
) {
893 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[i
], chain_in_accept
);
898 "-A FORWARD -i %s -j wanin\n" // generic from wan
899 "-A FORWARD -o %s -j wanout\n", // generic to wan
904 for (i
= 0; i
< wanfaces
.count
; ++i
) {
905 if (*(wanfaces
.iface
[i
].name
)) {
907 "-A FORWARD -i %s -j wanin\n" // generic from wan
908 "-A FORWARD -o %s -j wanout\n", // generic to wan
909 wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].name
);
913 ip46t_write("-A FORWARD -i %s -j %s\n", // from lan
914 lanface
, chain_out_accept
);
917 if (nvram_get_int("upnp_enable") & 3) {
918 ipt_write(":upnp - [0:0]\n");
919 for (i
= 0; i
< wanfaces
.count
; ++i
) {
920 if (*(wanfaces
.iface
[i
].name
)) {
921 ipt_write("-A FORWARD -i %s -j upnp\n",
922 wanfaces
.iface
[i
].name
);
928 if (nvram_match("multicast_pass", "1")) {
929 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
931 ipt_triggered(IPT_TABLE_FILTER
);
932 ipt_forward(IPT_TABLE_FILTER
);
938 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
941 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
942 if (ipt_source_strict(p
, src
, "dmz", NULL
))
943 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
950 // default policy: DROP
953 static void filter_log(void)
958 n
= nvram_get_int("log_limit");
959 if ((n
>= 1) && (n
<= 9999)) {
960 sprintf(limit
, "-m limit --limit %d/m", n
);
967 modprobe("ip6t_LOG");
969 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
972 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
976 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
977 "-A logdrop -j DROP\n"
978 ":logreject - [0:0]\n"
979 "-A logreject %s -j LOG --log-prefix \"REJECT \""
983 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
984 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
987 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
989 ":logaccept - [0:0]\n"
990 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
994 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
995 "-A logaccept -j ACCEPT\n",
1001 static void filter6_input(void)
1011 // RFC-4890, sec. 4.4.1
1012 const int allowed_local_icmpv6
[] =
1013 { 130, 131, 132, 133, 134, 135, 136,
1015 148, 149, 151, 152, 153 };
1018 "-A INPUT -m rt --rt-type 0 -j %s\n"
1019 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1020 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1024 modprobe("xt_length");
1025 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1028 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
1029 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
1031 modprobe("xt_recent");
1033 modprobe("ipt_recent");
1038 "-A shlimit -m recent --set --name shlimit\n"
1039 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1040 atoi(hit
) + 1, sec
, chain_in_drop
);
1043 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface
, nvram_safe_get("sshd_port"));
1044 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1045 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1048 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"));
1052 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
1053 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
1055 modprobe("xt_recent");
1057 modprobe("ipt_recent");
1062 "-A ftplimit -m recent --set --name ftp\n"
1063 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1064 atoi(hit
) + 1, sec
, chain_in_drop
);
1065 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1067 #endif // TCONFIG_FTP
1070 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1071 "-A INPUT -i lo -j ACCEPT\n",
1074 switch (get_ipv6_service()) {
1075 case IPV6_ANYCAST_6TO4
:
1076 case IPV6_NATIVE_DHCP
:
1077 // allow responses from the dhcpv6 server
1078 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept
);
1083 for (n
= 0; n
< sizeof(allowed_icmpv6
)/sizeof(int); n
++) {
1084 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[n
], chain_in_accept
);
1086 for (n
= 0; n
< sizeof(allowed_local_icmpv6
)/sizeof(int); n
++) {
1087 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6
[n
], chain_in_accept
);
1091 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
1094 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1096 if (ip6t_source(p
, s
, "remote management", NULL
)) {
1099 ip6t_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
1100 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
1103 if (nvram_get_int("sshd_remote")) {
1104 ip6t_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
1105 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
1115 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1116 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
1119 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1120 if (ip6t_source(p
, s
, "ftp", "remote access")) {
1121 ip6t_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
1122 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
1131 if (*chain_in_drop
== 'l') {
1132 ip6t_write( "-A INPUT -j %s\n", chain_in_drop
);
1135 // default policy: DROP
1140 static void filter_table(void)
1144 ":INPUT DROP [0:0]\n"
1145 ":OUTPUT ACCEPT [0:0]\n"
1153 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop
);
1156 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
1157 ip46t_write(":FORWARD DROP [0:0]\n");
1161 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1164 ip46t_write("COMMIT\n");
1168 // -----------------------------------------------------------------------------
1170 int start_firewall(void)
1173 struct dirent
*dirent
;
1178 char *iptrestore_argv
[] = { "iptables-restore", (char *)ipt_fname
, NULL
};
1180 char *ip6trestore_argv
[] = { "ip6tables-restore", (char *)ip6t_fname
, NULL
};
1183 simple_lock("firewall");
1184 simple_lock("restrictions");
1186 wanup
= check_wanup();
1188 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1190 /* NAT performance tweaks
1191 * These values can be overriden later if needed via firewall script
1193 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1194 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1195 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1196 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1197 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1198 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1199 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1200 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1201 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1202 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1203 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1204 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1206 /* DoS-related tweaks */
1207 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1208 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1209 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1211 wanproto
= get_wan_proto();
1212 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto
== WP_DISABLED
|| wanproto
== WP_STATIC
) ? "0" : "1", 0, 0);
1215 /* Force IGMPv2 due EMF limitations */
1216 if (nvram_get_int("emf_enable")) {
1217 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1218 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1222 n
= nvram_get_int("log_in");
1223 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
1224 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1226 n
= nvram_get_int("log_out");
1227 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
1228 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1229 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1231 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1233 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
1235 memcpy(&wanfaces
, get_wanfaces(), sizeof(wanfaces
));
1236 wanface
= wanfaces
.iface
[0].name
;
1238 strlcpy(wan6face
, get_wan6face(), sizeof(wan6face
));
1242 can_enable_fastnat
= (nvram_get_int("fastnat_disable") == 0);
1245 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
1246 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
1247 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
1250 block obviously spoofed IP addresses
1253 1 - do source validation by reversed path, as specified in RFC1812
1254 Recommended option for single homed hosts and stub network
1255 routers. Could cause troubles for complicated (not loop free)
1256 networks running a slow unreliable protocol (sort of RIP),
1257 or using static routes.
1258 0 - No source validation.
1260 c
= nvram_get("wan_ifname");
1261 /* mcast needs rp filter to be turned off only for non default iface */
1262 if (!(nvram_match("multicast_pass", "1")) || strcmp(wanface
, c
) == 0) c
= NULL
;
1264 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
1265 while ((dirent
= readdir(dir
)) != NULL
) {
1266 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
1267 f_write_string(s
, (c
&& strcmp(dirent
->d_name
, c
) == 0) ? "0" : "1", 0, 0);
1273 gateway_mode
= !nvram_match("wk_mode", "router");
1275 /* Remote management */
1276 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1277 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
1280 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
1281 notice_set("iptables", "Unable to create iptables restore file");
1282 simple_unlock("firewall");
1287 if ((ip6t_file
= fopen(ip6t_fname
, "w")) == NULL
) {
1288 notice_set("ip6tables", "Unable to create ip6tables restore file");
1289 simple_unlock("firewall");
1292 modprobe("nf_conntrack_ipv6");
1293 modprobe("ip6t_REJECT");
1295 /*Deon Thomas attempt to start xt_IMQ and imq */
1296 /*shibby - fix modprobing IMQ for kernel 2.4 */
1301 modprobe("ipt_IMQ");
1316 #ifdef DEBUG_IPTFILE
1318 simple_unlock("firewall");
1319 simple_unlock("restrictions");
1326 if (nvram_get_int("upnp_enable") & 3) {
1327 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
1328 if (killall("miniupnpd", SIGUSR2
) == 0) {
1329 f_wait_notexists("/etc/upnp/save", 5);
1333 notice_set("iptables", "");
1334 if (_eval(iptrestore_argv
, ">/var/notice/iptables", 0, NULL
) == 0) {
1336 notice_set("iptables", "");
1339 sprintf(s
, "%s.error", ipt_fname
);
1340 rename(ipt_fname
, s
);
1341 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1348 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1349 -A INPUT -i br0 -j ACCEPT
1353 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1354 -A FORWARD -i br0 -j ACCEPT
1360 if (ipv6_enabled()) {
1361 notice_set("ip6tables", "");
1362 if (_eval(ip6trestore_argv
, ">/var/notice/ip6tables", 0, NULL
) == 0) {
1363 notice_set("ip6tables", "");
1366 sprintf(s
, "%s.error", ip6t_fname
);
1367 rename(ip6t_fname
, s
);
1368 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1373 eval("ip6tables", "-F");
1374 eval("ip6tables", "-t", "mangle", "-F");
1378 if (nvram_get_int("upnp_enable") & 3) {
1379 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
1380 killall("miniupnpd", SIGUSR2
);
1384 enable_fastnat(can_enable_fastnat
);
1386 simple_unlock("restrictions");
1387 sched_restrictions();
1388 enable_ip_forward();
1390 led(LED_DMZ
, dmz_dst(NULL
));
1393 modprobe_r("nf_conntrack_ipv6");
1394 modprobe_r("ip6t_LOG");
1395 modprobe_r("ip6t_REJECT");
1398 modprobe_r("xt_layer7");
1399 modprobe_r("xt_recent");
1400 modprobe_r("xt_HL");
1401 modprobe_r("xt_length");
1402 modprobe_r("xt_web");
1403 modprobe_r("xt_webmon");
1404 modprobe_r("xt_dscp");
1406 modprobe_r("ipt_layer7");
1407 modprobe_r("ipt_recent");
1408 modprobe_r("ipt_TTL");
1409 modprobe_r("ipt_web");
1410 modprobe_r("ipt_webmon");
1411 modprobe_r("ipt_dscp");
1413 modprobe_r("ipt_ipp2p");
1415 unlink("/var/webmon/domain");
1416 unlink("/var/webmon/search");
1418 #ifdef TCONFIG_OPENVPN
1419 run_vpn_firewall_scripts();
1421 run_nvscript("script_fire", NULL
, 1);
1423 simple_unlock("firewall");
1427 int stop_firewall(void)
1433 #ifdef DEBUG_IPTFILE
1434 void create_test_iptfile(void)