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 static const char *fastnat_run_dir
= "/var/run/fastnat";
79 void allow_fastnat(const char *service
, int allow
)
83 snprintf(p
, sizeof(p
), "%s/%s", fastnat_run_dir
, service
);
88 mkdir_if_none(fastnat_run_dir
);
89 f_write_string(p
, "", 0, 0);
93 static inline int fastnat_allowed(void)
99 enabled
= !nvram_get_int("qos_enable") && !nvram_get_int("fastnat_disable");
101 if (enabled
&& (dir
= opendir(fastnat_run_dir
))) {
102 while ((dp
= readdir(dir
))) {
103 if (strcmp(dp
->d_name
, ".") == 0 || strcmp(dp
->d_name
, "..") == 0)
114 void try_enabling_fastnat(void)
116 f_write_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_fastnat",
117 fastnat_allowed() ? "1" : "0", 0, 0);
121 void enable_ip_forward(void)
125 0 - disabled (default)
128 Forward Packets between interfaces.
130 This variable is special, its change resets all configuration
131 parameters to their default state (RFC1122 for hosts, RFC1812
134 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
137 if (ipv6_enabled()) {
138 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "1", 0, 0);
139 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "1", 0, 0);
145 // -----------------------------------------------------------------------------
148 static int ip2cclass(char *ipaddr, char *new, int count)
152 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
153 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
158 static int dmz_dst(char *s
)
164 if (nvram_get_int("dmz_enable") <= 0) return 0;
166 p
= nvram_safe_get("dmz_ipaddr");
167 if ((ia
.s_addr
= inet_addr(p
)) == (in_addr_t
)-1) {
168 if (((n
= atoi(p
)) <= 0) || (n
>= 255)) return 0;
169 if (s
) sprintf(s
, "%s%d", lan_cclass
, n
);
173 if (s
) strcpy(s
, inet_ntoa(ia
));
177 void ipt_log_unresolved(const char *addr
, const char *addrtype
, const char *categ
, const char *name
)
181 pre
= (name
&& *name
) ? " for \"" : "";
182 post
= (name
&& *name
) ? "\"" : "";
184 syslog(LOG_WARNING
, "firewall: "
185 "%s: not using %s%s%s%s (could not resolve as valid %s address)",
186 categ
, addr
, pre
, (name
) ? : "", post
, (addrtype
) ? : "IP");
189 int ipt_addr(char *addr
, int maxlen
, const char *s
, const char *dir
, int af
,
190 int strict
, const char *categ
, const char *name
)
192 char p
[INET6_ADDRSTRLEN
* 2];
195 if ((s
) && (*s
) && (*dir
))
197 if (sscanf(s
, "%[0-9.]-%[0-9.]", p
, p
) == 2) {
198 snprintf(addr
, maxlen
, "-m iprange --%s-range %s", dir
, s
);
202 else if (sscanf(s
, "%[0-9A-Fa-f:]-%[0-9A-Fa-f:]", p
, p
) == 2) {
203 snprintf(addr
, maxlen
, "-m iprange --%s-range %s", dir
, s
);
208 snprintf(addr
, maxlen
, "-%c %s", dir
[0], s
);
209 if (sscanf(s
, "%[^/]/", p
)) {
211 r
= host_addrtypes(p
, strict
? af
: (IPT_V4
| IPT_V6
));
213 r
= host_addrtypes(p
, IPT_V4
);
221 r
= (IPT_V4
| IPT_V6
);
224 if ((r
== 0 || (strict
&& ((r
& af
) != af
))) && (categ
&& *categ
)) {
225 ipt_log_unresolved(s
, categ
, name
,
226 (af
& IPT_V4
& ~r
) ? "IPv4" : ((af
& IPT_V6
& ~r
) ? "IPv6" : NULL
));
232 #define ipt_source_strict(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 1, categ, name)
233 #define ipt_source(s, src, categ, name) ipt_addr(src, 64, s, "src", IPT_V4, 0, categ, name)
234 #define ip6t_source(s, src, categ, name) ipt_addr(src, 128, s, "src", IPT_V6, 0, categ, name)
237 static void get_src(const char *nv, char *src)
241 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
242 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
250 void ipt_write(const char *format
, ...)
254 va_start(args
, format
);
255 vfprintf(ipt_file
, format
, args
);
259 void ip6t_write(const char *format
, ...)
264 va_start(args
, format
);
265 vfprintf(ip6t_file
, format
, args
);
270 // -----------------------------------------------------------------------------
272 int ipt_dscp(const char *v
, char *opt
)
281 n
= strtoul(v
, NULL
, 0);
283 sprintf(opt
, " -m dscp --dscp 0x%02X", n
);
288 modprobe("ipt_dscp");
293 // -----------------------------------------------------------------------------
296 int ipt_ipp2p(const char *v
, char *opt
)
305 strcpy(opt
, "-m ipp2p ");
306 if ((n
& 0xFFF) == 0xFFF) {
307 strcat(opt
, "--ipp2p");
311 if (n
& 0x0001) strcat(opt
, "--apple ");
312 if (n
& 0x0002) strcat(opt
, "--ares ");
313 if (n
& 0x0004) strcat(opt
, "--bit ");
314 if (n
& 0x0008) strcat(opt
, "--dc ");
315 if (n
& 0x0010) strcat(opt
, "--edk ");
316 if (n
& 0x0020) strcat(opt
, "--gnu ");
317 if (n
& 0x0040) strcat(opt
, "--kazaa ");
318 if (n
& 0x0080) strcat(opt
, "--mute ");
319 if (n
& 0x0100) strcat(opt
, "--soul ");
320 if (n
& 0x0200) strcat(opt
, "--waste ");
321 if (n
& 0x0400) strcat(opt
, "--winmx ");
322 if (n
& 0x0800) strcat(opt
, "--xdcc ");
325 modprobe("ipt_ipp2p");
330 // -----------------------------------------------------------------------------
335 // This L7 matches inbound traffic, caches the results, then the L7 outbound
336 // should read the cached result and set the appropriate marks -- zzz
337 void ipt_layer7_inbound(void)
342 if (!layer7_in
) return;
344 en
= nvram_match("nf_l7in", "1");
346 ipt_write(":L7in - [0:0]\n");
347 for (i
= 0; i
< wanfaces
.count
; ++i
) {
348 if (*(wanfaces
.iface
[i
].name
)) {
349 ipt_write("-A FORWARD -i %s -j L7in\n",
350 wanfaces
.iface
[i
].name
);
358 ipt_write("-A L7in %s -j RETURN\n", *p
);
360 can_enable_fastnat
= 0;
370 int ipt_layer7(const char *v
, char *opt
)
376 if (*v
== 0) return 0;
377 if (strlen(v
) > 32) return -1;
379 path
= "/etc/l7-extra";
380 sprintf(s
, "%s/%s.pat", path
, v
);
382 path
= "/etc/l7-protocols";
383 sprintf(s
, "%s/%s.pat", path
, v
);
385 syslog(LOG_ERR
, "L7 %s was not found", v
);
390 sprintf(opt
, "-m layer7 --l7dir %s --l7proto %s", path
, v
);
392 if (nvram_match("nf_l7in", "1")) {
393 if (!layer7_in
) layer7_in
= calloc(51, sizeof(char *));
399 if (strcmp(*p
, opt
) == 0) return 1;
402 if (((p
- layer7_in
) / sizeof(char *)) < 50) *p
= strdup(opt
);
407 modprobe("xt_layer7");
409 modprobe("ipt_layer7");
415 // -----------------------------------------------------------------------------
417 static void save_webmon(void)
419 eval("cp", "/proc/webmon_recent_domains", "/var/webmon/domain");
420 eval("cp", "/proc/webmon_recent_searches", "/var/webmon/search");
423 static void ipt_webmon()
425 int wmtype
, clear
, i
;
431 if (!nvram_get_int("log_wm")) return;
434 can_enable_fastnat
= 0;
436 wmtype
= nvram_get_int("log_wmtype");
437 clear
= nvram_get_int("log_wmclear");
439 ip46t_write(":monitor - [0:0]\n");
442 strlcpy(t
, wmtype
== 1 ? nvram_safe_get("log_wmip") : "", sizeof(t
));
445 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
447 if ((ok
= ipt_addr(src
, sizeof(src
), p
, "src", IPT_V4
|IPT_V6
, 0, "webmon", NULL
))) {
449 if (*wan6face
&& (ok
& IPT_V6
))
450 ip6t_write("-A FORWARD -o %s %s -j monitor\n", wan6face
, src
);
453 for (i
= 0; i
< wanfaces
.count
; ++i
) {
454 if (*(wanfaces
.iface
[i
].name
)) {
455 ipt_write("-A FORWARD -o %s %s -j monitor\n",
456 wanfaces
.iface
[i
].name
, src
);
468 strlcpy(t
, nvram_safe_get("log_wmip"), sizeof(t
));
471 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
472 if ((ok
= ipt_addr(src
, sizeof(src
), p
, "src", IPT_V4
|IPT_V6
, 0, "webmon", NULL
))) {
474 ip46t_flagged_write(ok
, "-A monitor %s -j RETURN\n", src
);
482 "-A monitor -p tcp -m webmon "
483 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
484 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
485 (clear
& 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
486 (clear
& 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
489 modprobe("xt_webmon");
491 modprobe("ipt_webmon");
496 // -----------------------------------------------------------------------------
498 // -----------------------------------------------------------------------------
500 static void mangle_table(void)
507 ":PREROUTING ACCEPT [0:0]\n"
508 ":OUTPUT ACCEPT [0:0]\n");
516 p
= nvram_safe_get("nf_ttl");
517 if (strncmp(p
, "c:", 2) == 0) {
520 p
= (ttl
>= 0 && ttl
<= 255) ? "set" : NULL
;
522 else if ((ttl
= atoi(p
)) != 0) {
530 if (ttl
> 255) p
= NULL
;
540 // set TTL on primary WAN iface only
541 wanface
= wanfaces
.iface
[0].name
;
543 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
544 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
548 // FIXME: IPv6 HL should be configurable separately from TTL.
549 // disable it until GUI setting is implemented.
552 "-I PREROUTING -i %s -j HL --hl-%s %d\n"
553 "-I POSTROUTING -o %s -j HL --hl-%s %d\n",
561 ip46t_write("COMMIT\n");
564 // -----------------------------------------------------------------------------
566 // -----------------------------------------------------------------------------
568 static void nat_table(void)
579 ":PREROUTING ACCEPT [0:0]\n"
580 ":POSTROUTING ACCEPT [0:0]\n"
581 ":OUTPUT ACCEPT [0:0]\n"
583 chain_wan_prerouting
);
589 strlcpy(lanaddr
, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr
));
590 strlcpy(lanmask
, nvram_safe_get("lan_netmask"), sizeof(lanmask
));
592 for (i
= 0; i
< wanfaces
.count
; ++i
) {
593 if (*(wanfaces
.iface
[i
].name
)) {
594 // Drop incoming packets which destination IP address is to our LAN side directly
595 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
596 wanfaces
.iface
[i
].name
,
597 lanaddr
, lanmask
); // note: ipt will correct lanaddr
599 // chain_wan_prerouting
601 ipt_write("-A PREROUTING -d %s -j %s\n",
602 wanfaces
.iface
[i
].ip
, chain_wan_prerouting
);
608 if (nvram_match("dns_intcpt", "1")) {
609 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
615 // ICMP packets are always redirected to INPUT chains
616 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting
, lanaddr
);
618 ipt_forward(IPT_TABLE_NAT
);
619 ipt_triggered(IPT_TABLE_NAT
);
622 if (nvram_get_int("upnp_enable") & 3) {
623 ipt_write(":upnp - [0:0]\n");
625 for (i
= 0; i
< wanfaces
.count
; ++i
) {
626 if (*(wanfaces
.iface
[i
].name
)) {
628 // ! for loopback (all) to work
629 ipt_write("-A PREROUTING -d %s -j upnp\n", wanfaces
.iface
[i
].ip
);
632 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces
.iface
[i
].name
);
640 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
643 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
644 if (ipt_source_strict(p
, src
, "dmz", NULL
))
645 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting
, src
, dst
);
654 switch (get_ipv6_service()) {
656 // avoid NATing proto-41 packets when using 6in4 tunnel
662 for (i
= 0; i
< wanfaces
.count
; ++i
) {
663 if (*(wanfaces
.iface
[i
].name
)) {
664 if ((!wanup
) || (nvram_get_int("net_snat") != 1))
665 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p
, wanfaces
.iface
[i
].name
);
667 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p
, wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].ip
);
671 switch (nvram_get_int("nf_loopback")) {
672 case 1: // 1 = forwarded-only
673 case 2: // 2 = disable
675 default: // 0 = all (same as block_loopback=0)
676 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
684 ipt_write("COMMIT\n");
687 // -----------------------------------------------------------------------------
689 // -----------------------------------------------------------------------------
691 static void filter_input(void)
701 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
702 for (n
= 0; n
< wanfaces
.count
; ++n
) {
703 if (*(wanfaces
.iface
[n
].name
)) {
704 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanfaces
.iface
[n
].ip
);
710 "-A INPUT -m state --state INVALID -j DROP\n"
711 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
713 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
714 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
716 ? what if the user uses the start button in GUI ?
717 if (nvram_get_int("telnetd_eas"))
718 if (nvram_get_int("sshd_eas"))
721 modprobe("xt_recent");
723 modprobe("ipt_recent");
728 "-A shlimit -m recent --set --name shlimit\n"
729 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
730 atoi(hit
) + 1, sec
, chain_in_drop
);
733 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
734 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
735 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
738 if (n
& 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
742 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
743 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
745 modprobe("xt_recent");
747 modprobe("ipt_recent");
752 "-A ftplimit -m recent --set --name ftp\n"
753 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
754 atoi(hit
) + 1, sec
, chain_in_drop
);
755 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
760 "-A INPUT -i %s -j ACCEPT\n"
761 "-A INPUT -i lo -j ACCEPT\n",
765 n
= get_ipv6_service();
767 case IPV6_ANYCAST_6TO4
:
769 // Accept ICMP requests from the remote tunnel endpoint
770 if (n
== IPV6_ANYCAST_6TO4
)
771 sprintf(s
, "192.88.99.%d", nvram_get_int("ipv6_relay"));
773 strlcpy(s
, nvram_safe_get("ipv6_tun_v4end"), sizeof(s
));
774 if (*s
&& strcmp(s
, "0.0.0.0") != 0)
775 ipt_write("-A INPUT -p icmp -s %s -j %s\n", s
, chain_in_accept
);
776 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept
);
781 // ICMP request from WAN interface
782 if (nvram_match("block_wan", "0")) {
783 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
784 ipt_write("-A INPUT -p icmp -m limit --limit 1/second -j %s\n", chain_in_accept
);
785 // allow udp traceroute packets
786 ipt_write("-A INPUT -p udp --dport 33434:33534 -m limit --limit 5/second -j %s\n", chain_in_accept
);
789 /* Accept incoming packets from broken dhcp servers, which are sending replies
790 * from addresses other than used for query. This could lead to a lower level
791 * of security, so allow to disable it via nvram variable.
793 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
794 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept
);
797 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
800 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
802 if (ipt_source(p
, s
, "remote management", NULL
)) {
805 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
806 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
809 if (nvram_get_int("sshd_remote")) {
810 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
811 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
819 #ifdef TCONFIG_FTP // !!TB - FTP Server
820 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
821 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
824 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
825 if (ipt_source(p
, s
, "ftp", "remote access")) {
826 ipt_write("-A INPUT -p tcp %s --dport %s -j %s\n",
827 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
835 // IGMP query from WAN interface
836 if (nvram_match("multicast_pass", "1")) {
837 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
838 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
841 // Routing protocol, RIP, accept
842 if (nvram_invmatch("dr_wan_rx", "0")) {
843 ipt_write("-A INPUT -p udp --dport 520 -j ACCEPT\n");
847 if (*chain_in_drop
== 'l') {
848 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
851 // default policy: DROP
854 // clamp TCP MSS to PMTU of WAN interface (IPv4 only?)
855 static void clampmss(void)
857 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
859 switch (get_ipv6_service()) {
860 case IPV6_ANYCAST_6TO4
:
862 ip6t_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
868 static void filter_forward(void)
878 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
882 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
887 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
889 // clamp tcp mss to pmtu
895 ipt_layer7_inbound();
903 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
906 // Filter out invalid WAN->WAN connections
908 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face
, lanface
, chain_in_drop
);
911 modprobe("xt_length");
912 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
916 for (i
= 0; i
< sizeof(allowed_icmpv6
)/sizeof(int); ++i
) {
917 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[i
], chain_in_accept
);
922 "-A FORWARD -i %s -j wanin\n" // generic from wan
923 "-A FORWARD -o %s -j wanout\n", // generic to wan
928 for (i
= 0; i
< wanfaces
.count
; ++i
) {
929 if (*(wanfaces
.iface
[i
].name
)) {
931 "-A FORWARD -i %s -j wanin\n" // generic from wan
932 "-A FORWARD -o %s -j wanout\n", // generic to wan
933 wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].name
);
937 ip46t_write("-A FORWARD -i %s -j %s\n", // from lan
938 lanface
, chain_out_accept
);
941 if (nvram_get_int("upnp_enable") & 3) {
942 ipt_write(":upnp - [0:0]\n");
943 for (i
= 0; i
< wanfaces
.count
; ++i
) {
944 if (*(wanfaces
.iface
[i
].name
)) {
945 ipt_write("-A FORWARD -i %s -j upnp\n",
946 wanfaces
.iface
[i
].name
);
952 if (nvram_match("multicast_pass", "1")) {
953 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
955 ipt_triggered(IPT_TABLE_FILTER
);
956 ipt_forward(IPT_TABLE_FILTER
);
962 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
965 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
966 if (ipt_source_strict(p
, src
, "dmz", NULL
))
967 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
974 // default policy: DROP
977 static void filter_log(void)
982 n
= nvram_get_int("log_limit");
983 if ((n
>= 1) && (n
<= 9999)) {
984 sprintf(limit
, "-m limit --limit %d/m", n
);
991 modprobe("ip6t_LOG");
993 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
996 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1000 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1001 "-A logdrop -j DROP\n"
1002 ":logreject - [0:0]\n"
1003 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1007 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1008 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1011 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
1013 ":logaccept - [0:0]\n"
1014 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1018 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1019 "-A logaccept -j ACCEPT\n",
1025 static void filter6_input(void)
1035 // RFC-4890, sec. 4.4.1
1036 const int allowed_local_icmpv6
[] =
1037 { 130, 131, 132, 133, 134, 135, 136,
1039 148, 149, 151, 152, 153 };
1042 "-A INPUT -m rt --rt-type 0 -j %s\n"
1043 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1044 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1048 modprobe("xt_length");
1049 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1052 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
1053 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
1055 modprobe("xt_recent");
1057 modprobe("ipt_recent");
1062 "-A shlimit -m recent --set --name shlimit\n"
1063 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1064 atoi(hit
) + 1, sec
, chain_in_drop
);
1067 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface
, nvram_safe_get("sshd_port"));
1068 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1069 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1072 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"));
1076 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
1077 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
1079 modprobe("xt_recent");
1081 modprobe("ipt_recent");
1086 "-A ftplimit -m recent --set --name ftp\n"
1087 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1088 atoi(hit
) + 1, sec
, chain_in_drop
);
1089 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1091 #endif // TCONFIG_FTP
1094 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1095 "-A INPUT -i lo -j ACCEPT\n",
1098 switch (get_ipv6_service()) {
1099 case IPV6_ANYCAST_6TO4
:
1100 case IPV6_NATIVE_DHCP
:
1101 // allow responses from the dhcpv6 server
1102 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept
);
1107 for (n
= 0; n
< sizeof(allowed_icmpv6
)/sizeof(int); n
++) {
1108 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[n
], chain_in_accept
);
1110 for (n
= 0; n
< sizeof(allowed_local_icmpv6
)/sizeof(int); n
++) {
1111 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6
[n
], chain_in_accept
);
1115 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
1118 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1120 if (ip6t_source(p
, s
, "remote management", NULL
)) {
1123 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1124 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
1127 if (nvram_get_int("sshd_remote")) {
1128 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1129 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
1139 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1140 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
1143 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1144 if (ip6t_source(p
, s
, "ftp", "remote access")) {
1145 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1146 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
1155 if (*chain_in_drop
== 'l') {
1156 ip6t_write( "-A INPUT -j %s\n", chain_in_drop
);
1159 // default policy: DROP
1164 static void filter_table(void)
1168 ":INPUT DROP [0:0]\n"
1169 ":OUTPUT ACCEPT [0:0]\n"
1177 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop
);
1180 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
1181 ip46t_write(":FORWARD DROP [0:0]\n");
1185 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1188 ip46t_write("COMMIT\n");
1192 // -----------------------------------------------------------------------------
1194 int start_firewall(void)
1197 struct dirent
*dirent
;
1202 char *iptrestore_argv
[] = { "iptables-restore", (char *)ipt_fname
, NULL
};
1204 char *ip6trestore_argv
[] = { "ip6tables-restore", (char *)ip6t_fname
, NULL
};
1207 simple_lock("firewall");
1208 simple_lock("restrictions");
1210 wanup
= check_wanup();
1212 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1214 /* NAT performance tweaks
1215 * These values can be overriden later if needed via firewall script
1217 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1218 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1219 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1220 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1221 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1222 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1223 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1224 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1225 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1226 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1227 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1228 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1230 /* DoS-related tweaks */
1231 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1232 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1233 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1235 wanproto
= get_wan_proto();
1236 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto
== WP_DISABLED
|| wanproto
== WP_STATIC
) ? "0" : "1", 0, 0);
1239 /* Force IGMPv2 due EMF limitations */
1240 if (nvram_get_int("emf_enable")) {
1241 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1242 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1246 n
= nvram_get_int("log_in");
1247 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
1248 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1250 n
= nvram_get_int("log_out");
1251 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
1252 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1253 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1255 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1257 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
1259 memcpy(&wanfaces
, get_wanfaces(), sizeof(wanfaces
));
1260 wanface
= wanfaces
.iface
[0].name
;
1262 strlcpy(wan6face
, get_wan6face(), sizeof(wan6face
));
1266 can_enable_fastnat
= 1;
1269 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
1270 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
1271 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
1274 block obviously spoofed IP addresses
1277 1 - do source validation by reversed path, as specified in RFC1812
1278 Recommended option for single homed hosts and stub network
1279 routers. Could cause troubles for complicated (not loop free)
1280 networks running a slow unreliable protocol (sort of RIP),
1281 or using static routes.
1282 0 - No source validation.
1284 c
= nvram_get("wan_ifname");
1285 /* mcast needs rp filter to be turned off only for non default iface */
1286 if (!(nvram_match("multicast_pass", "1")) || strcmp(wanface
, c
) == 0) c
= NULL
;
1288 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
1289 while ((dirent
= readdir(dir
)) != NULL
) {
1290 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
1291 f_write_string(s
, (c
&& strcmp(dirent
->d_name
, c
) == 0) ? "0" : "1", 0, 0);
1297 gateway_mode
= !nvram_match("wk_mode", "router");
1299 /* Remote management */
1300 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1301 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
1304 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
1305 notice_set("iptables", "Unable to create iptables restore file");
1306 simple_unlock("firewall");
1311 if ((ip6t_file
= fopen(ip6t_fname
, "w")) == NULL
) {
1312 notice_set("ip6tables", "Unable to create ip6tables restore file");
1313 simple_unlock("firewall");
1316 modprobe("nf_conntrack_ipv6");
1317 modprobe("ip6t_REJECT");
1319 /*Deon Thomas attempt to start xt_IMQ and imq */
1320 /*shibby - fix modprobing IMQ for kernel 2.4 */
1325 modprobe("ipt_IMQ");
1340 #ifdef DEBUG_IPTFILE
1342 simple_unlock("firewall");
1343 simple_unlock("restrictions");
1350 if (nvram_get_int("upnp_enable") & 3) {
1351 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
1352 if (killall("miniupnpd", SIGUSR2
) == 0) {
1353 f_wait_notexists("/etc/upnp/save", 5);
1357 notice_set("iptables", "");
1358 if (_eval(iptrestore_argv
, ">/var/notice/iptables", 0, NULL
) == 0) {
1360 notice_set("iptables", "");
1363 sprintf(s
, "%s.error", ipt_fname
);
1364 rename(ipt_fname
, s
);
1365 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1372 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1373 -A INPUT -i br0 -j ACCEPT
1377 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1378 -A FORWARD -i br0 -j ACCEPT
1384 if (ipv6_enabled()) {
1385 notice_set("ip6tables", "");
1386 if (_eval(ip6trestore_argv
, ">/var/notice/ip6tables", 0, NULL
) == 0) {
1387 notice_set("ip6tables", "");
1390 sprintf(s
, "%s.error", ip6t_fname
);
1391 rename(ip6t_fname
, s
);
1392 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1397 eval("ip6tables", "-F");
1398 eval("ip6tables", "-t", "mangle", "-F");
1402 if (nvram_get_int("upnp_enable") & 3) {
1403 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
1404 killall("miniupnpd", SIGUSR2
);
1407 simple_unlock("restrictions");
1408 sched_restrictions();
1409 enable_ip_forward();
1411 led(LED_DMZ
, dmz_dst(NULL
));
1414 modprobe_r("nf_conntrack_ipv6");
1415 modprobe_r("ip6t_LOG");
1416 modprobe_r("ip6t_REJECT");
1419 modprobe_r("xt_layer7");
1420 modprobe_r("xt_recent");
1421 modprobe_r("xt_HL");
1422 modprobe_r("xt_length");
1423 modprobe_r("xt_web");
1424 modprobe_r("xt_webmon");
1425 modprobe_r("xt_dscp");
1427 modprobe_r("ipt_layer7");
1428 modprobe_r("ipt_recent");
1429 modprobe_r("ipt_TTL");
1430 modprobe_r("ipt_web");
1431 modprobe_r("ipt_webmon");
1432 modprobe_r("ipt_dscp");
1434 modprobe_r("ipt_ipp2p");
1436 unlink("/var/webmon/domain");
1437 unlink("/var/webmon/search");
1439 #ifdef TCONFIG_OPENVPN
1440 run_vpn_firewall_scripts();
1442 run_nvscript("script_fire", NULL
, 1);
1445 allow_fastnat("firewall", can_enable_fastnat
);
1446 try_enabling_fastnat();
1449 simple_unlock("firewall");
1453 int stop_firewall(void)
1459 #ifdef DEBUG_IPTFILE
1460 void create_test_iptfile(void)