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)
858 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
860 int rmtu
= nvram_get_int("wan_run_mtu");
861 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
863 ipt_write("--clamp-mss-to-pmtu\n");
866 ipt_write("--set-mss %d\n", rmtu
- 40);
871 static void filter_forward(void)
881 "-A FORWARD -m rt --rt-type 0 -j DROP\n");
885 "-A FORWARD -i %s -o %s -j ACCEPT\n", // accept all lan to lan
890 "-A FORWARD -m state --state INVALID -j DROP\n"); // drop if INVALID state
892 // clamp tcp mss to pmtu
898 ipt_layer7_inbound();
906 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
909 // Filter out invalid WAN->WAN connections
911 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face
, lanface
, chain_in_drop
);
914 modprobe("xt_length");
915 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
919 for (i
= 0; i
< sizeof(allowed_icmpv6
)/sizeof(int); ++i
) {
920 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[i
], chain_in_accept
);
925 "-A FORWARD -i %s -j wanin\n" // generic from wan
926 "-A FORWARD -o %s -j wanout\n", // generic to wan
931 for (i
= 0; i
< wanfaces
.count
; ++i
) {
932 if (*(wanfaces
.iface
[i
].name
)) {
934 "-A FORWARD -i %s -j wanin\n" // generic from wan
935 "-A FORWARD -o %s -j wanout\n", // generic to wan
936 wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].name
);
940 ip46t_write("-A FORWARD -i %s -j %s\n", // from lan
941 lanface
, chain_out_accept
);
944 if (nvram_get_int("upnp_enable") & 3) {
945 ipt_write(":upnp - [0:0]\n");
946 for (i
= 0; i
< wanfaces
.count
; ++i
) {
947 if (*(wanfaces
.iface
[i
].name
)) {
948 ipt_write("-A FORWARD -i %s -j upnp\n",
949 wanfaces
.iface
[i
].name
);
955 if (nvram_match("multicast_pass", "1")) {
956 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
958 ipt_triggered(IPT_TABLE_FILTER
);
959 ipt_forward(IPT_TABLE_FILTER
);
965 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
968 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
969 if (ipt_source_strict(p
, src
, "dmz", NULL
))
970 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
977 // default policy: DROP
980 static void filter_log(void)
985 n
= nvram_get_int("log_limit");
986 if ((n
>= 1) && (n
<= 9999)) {
987 sprintf(limit
, "-m limit --limit %d/m", n
);
994 modprobe("ip6t_LOG");
996 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
999 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \""
1003 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1004 "-A logdrop -j DROP\n"
1005 ":logreject - [0:0]\n"
1006 "-A logreject %s -j LOG --log-prefix \"REJECT \""
1010 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1011 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
1014 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
1016 ":logaccept - [0:0]\n"
1017 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \""
1021 " --log-tcp-sequence --log-tcp-options --log-ip-options\n"
1022 "-A logaccept -j ACCEPT\n",
1028 static void filter6_input(void)
1038 // RFC-4890, sec. 4.4.1
1039 const int allowed_local_icmpv6
[] =
1040 { 130, 131, 132, 133, 134, 135, 136,
1042 148, 149, 151, 152, 153 };
1045 "-A INPUT -m rt --rt-type 0 -j %s\n"
1046 /* "-A INPUT -m state --state INVALID -j DROP\n" */
1047 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
1051 modprobe("xt_length");
1052 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
1055 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
1056 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
1058 modprobe("xt_recent");
1060 modprobe("ipt_recent");
1065 "-A shlimit -m recent --set --name shlimit\n"
1066 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
1067 atoi(hit
) + 1, sec
, chain_in_drop
);
1070 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface
, nvram_safe_get("sshd_port"));
1071 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
1072 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
1075 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"));
1079 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
1080 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
1082 modprobe("xt_recent");
1084 modprobe("ipt_recent");
1089 "-A ftplimit -m recent --set --name ftp\n"
1090 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
1091 atoi(hit
) + 1, sec
, chain_in_drop
);
1092 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
1094 #endif // TCONFIG_FTP
1097 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
1098 "-A INPUT -i lo -j ACCEPT\n",
1101 switch (get_ipv6_service()) {
1102 case IPV6_ANYCAST_6TO4
:
1103 case IPV6_NATIVE_DHCP
:
1104 // allow responses from the dhcpv6 server
1105 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept
);
1110 for (n
= 0; n
< sizeof(allowed_icmpv6
)/sizeof(int); n
++) {
1111 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[n
], chain_in_accept
);
1113 for (n
= 0; n
< sizeof(allowed_local_icmpv6
)/sizeof(int); n
++) {
1114 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_local_icmpv6
[n
], chain_in_accept
);
1118 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
1121 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1123 if (ip6t_source(p
, s
, "remote management", NULL
)) {
1126 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1127 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
1130 if (nvram_get_int("sshd_remote")) {
1131 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1132 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
1142 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
1143 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
1146 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
1147 if (ip6t_source(p
, s
, "ftp", "remote access")) {
1148 ip6t_write("-A INPUT -p tcp %s --dport %s -j %s\n",
1149 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
1158 if (*chain_in_drop
== 'l') {
1159 ip6t_write( "-A INPUT -j %s\n", chain_in_drop
);
1162 // default policy: DROP
1167 static void filter_table(void)
1171 ":INPUT DROP [0:0]\n"
1172 ":OUTPUT ACCEPT [0:0]\n"
1180 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop
);
1183 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
1184 ip46t_write(":FORWARD DROP [0:0]\n");
1188 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1191 ip46t_write("COMMIT\n");
1195 // -----------------------------------------------------------------------------
1197 int start_firewall(void)
1200 struct dirent
*dirent
;
1205 char *iptrestore_argv
[] = { "iptables-restore", (char *)ipt_fname
, NULL
};
1207 char *ip6trestore_argv
[] = { "ip6tables-restore", (char *)ip6t_fname
, NULL
};
1210 simple_lock("firewall");
1211 simple_lock("restrictions");
1213 wanup
= check_wanup();
1215 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1217 /* NAT performance tweaks
1218 * These values can be overriden later if needed via firewall script
1220 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1221 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1222 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1223 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1224 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1225 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1226 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1227 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1228 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1229 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1230 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1231 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1233 /* DoS-related tweaks */
1234 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1235 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1236 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1238 wanproto
= get_wan_proto();
1239 f_write_string("/proc/sys/net/ipv4/ip_dynaddr", (wanproto
== WP_DISABLED
|| wanproto
== WP_STATIC
) ? "0" : "1", 0, 0);
1242 /* Force IGMPv2 due EMF limitations */
1243 if (nvram_get_int("emf_enable")) {
1244 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1245 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1249 n
= nvram_get_int("log_in");
1250 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
1251 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1253 n
= nvram_get_int("log_out");
1254 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
1255 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1256 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1258 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1260 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
1262 memcpy(&wanfaces
, get_wanfaces(), sizeof(wanfaces
));
1263 wanface
= wanfaces
.iface
[0].name
;
1265 strlcpy(wan6face
, get_wan6face(), sizeof(wan6face
));
1269 can_enable_fastnat
= 1;
1272 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
1273 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
1274 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
1277 block obviously spoofed IP addresses
1280 1 - do source validation by reversed path, as specified in RFC1812
1281 Recommended option for single homed hosts and stub network
1282 routers. Could cause troubles for complicated (not loop free)
1283 networks running a slow unreliable protocol (sort of RIP),
1284 or using static routes.
1285 0 - No source validation.
1287 c
= nvram_get("wan_ifname");
1288 /* mcast needs rp filter to be turned off only for non default iface */
1289 if (!(nvram_match("multicast_pass", "1")) || strcmp(wanface
, c
) == 0) c
= NULL
;
1291 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
1292 while ((dirent
= readdir(dir
)) != NULL
) {
1293 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
1294 f_write_string(s
, (c
&& strcmp(dirent
->d_name
, c
) == 0) ? "0" : "1", 0, 0);
1300 gateway_mode
= !nvram_match("wk_mode", "router");
1302 /* Remote management */
1303 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1304 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
1307 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
1308 notice_set("iptables", "Unable to create iptables restore file");
1309 simple_unlock("firewall");
1314 if ((ip6t_file
= fopen(ip6t_fname
, "w")) == NULL
) {
1315 notice_set("ip6tables", "Unable to create ip6tables restore file");
1316 simple_unlock("firewall");
1319 modprobe("nf_conntrack_ipv6");
1320 modprobe("ip6t_REJECT");
1322 /*Deon Thomas attempt to start xt_IMQ and imq */
1323 /*shibby - fix modprobing IMQ for kernel 2.4 */
1328 modprobe("ipt_IMQ");
1343 #ifdef DEBUG_IPTFILE
1345 simple_unlock("firewall");
1346 simple_unlock("restrictions");
1353 if (nvram_get_int("upnp_enable") & 3) {
1354 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
1355 if (killall("miniupnpd", SIGUSR2
) == 0) {
1356 f_wait_notexists("/etc/upnp/save", 5);
1360 notice_set("iptables", "");
1361 if (_eval(iptrestore_argv
, ">/var/notice/iptables", 0, NULL
) == 0) {
1363 notice_set("iptables", "");
1366 sprintf(s
, "%s.error", ipt_fname
);
1367 rename(ipt_fname
, s
);
1368 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1375 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1376 -A INPUT -i br0 -j ACCEPT
1380 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1381 -A FORWARD -i br0 -j ACCEPT
1387 if (ipv6_enabled()) {
1388 notice_set("ip6tables", "");
1389 if (_eval(ip6trestore_argv
, ">/var/notice/ip6tables", 0, NULL
) == 0) {
1390 notice_set("ip6tables", "");
1393 sprintf(s
, "%s.error", ip6t_fname
);
1394 rename(ip6t_fname
, s
);
1395 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1400 eval("ip6tables", "-F");
1401 eval("ip6tables", "-t", "mangle", "-F");
1405 if (nvram_get_int("upnp_enable") & 3) {
1406 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
1407 killall("miniupnpd", SIGUSR2
);
1410 simple_unlock("restrictions");
1411 sched_restrictions();
1412 enable_ip_forward();
1414 led(LED_DMZ
, dmz_dst(NULL
));
1417 modprobe_r("nf_conntrack_ipv6");
1418 modprobe_r("ip6t_LOG");
1419 modprobe_r("ip6t_REJECT");
1422 modprobe_r("xt_layer7");
1423 modprobe_r("xt_recent");
1424 modprobe_r("xt_HL");
1425 modprobe_r("xt_length");
1426 modprobe_r("xt_web");
1427 modprobe_r("xt_webmon");
1428 modprobe_r("xt_dscp");
1430 modprobe_r("ipt_layer7");
1431 modprobe_r("ipt_recent");
1432 modprobe_r("ipt_TTL");
1433 modprobe_r("ipt_web");
1434 modprobe_r("ipt_webmon");
1435 modprobe_r("ipt_dscp");
1437 modprobe_r("ipt_ipp2p");
1439 unlink("/var/webmon/domain");
1440 unlink("/var/webmon/search");
1442 #ifdef TCONFIG_OPENVPN
1443 run_vpn_firewall_scripts();
1445 run_nvscript("script_fire", NULL
, 1);
1448 allow_fastnat("firewall", can_enable_fastnat
);
1449 try_enabling_fastnat();
1454 simple_unlock("firewall");
1458 int stop_firewall(void)
1464 #ifdef DEBUG_IPTFILE
1465 void create_test_iptfile(void)