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];
40 static int debug_only
= 0;
43 static int gateway_mode
;
44 static int remotemanage
;
47 const char *chain_in_drop
;
48 const char *chain_in_accept
;
49 const char *chain_out_drop
;
50 const char *chain_out_accept
;
51 const char *chain_out_reject
;
53 const char chain_wan_prerouting
[] = "WANPREROUTING";
54 const char ipt_fname
[] = "/etc/iptables";
58 const char ip6t_fname
[] = "/etc/ip6tables";
68 // -----------------------------------------------------------------------------
71 void enable_ip_forward(void)
75 0 - disabled (default)
78 Forward Packets between interfaces.
80 This variable is special, its change resets all configuration
81 parameters to their default state (RFC1122 for hosts, RFC1812
84 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
88 f_write_string("/proc/sys/net/ipv6/conf/default/forwarding", "1", 0, 0);
89 f_write_string("/proc/sys/net/ipv6/conf/all/forwarding", "1", 0, 0);
95 // -----------------------------------------------------------------------------
98 static int ip2cclass(char *ipaddr, char *new, int count)
102 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
103 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
108 static int dmz_dst(char *s
)
114 if (nvram_get_int("dmz_enable") <= 0) return 0;
116 p
= nvram_safe_get("dmz_ipaddr");
117 if ((ia
.s_addr
= inet_addr(p
)) == (in_addr_t
)-1) {
118 if (((n
= atoi(p
)) <= 0) || (n
>= 255)) return 0;
119 if (s
) sprintf(s
, "%s%d", lan_cclass
, n
);
123 if (s
) strcpy(s
, inet_ntoa(ia
));
127 void ipt_addr(char *addr
, int maxlen
, const char *s
, const char *dir
)
133 if (sscanf(s
, "%[0-9.]-%[0-9.]", p
, p
) == 2)
134 snprintf(addr
, maxlen
, "-m iprange --%s-range %s", dir
, s
);
136 snprintf(addr
, maxlen
, "-%c %s", dir
[0], s
);
142 static inline void ipt_source(const char *s
, char *src
)
144 ipt_addr(src
, 64, s
, "src");
148 static void get_src(const char *nv, char *src)
152 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
153 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
161 void ipt_write(const char *format
, ...)
165 va_start(args
, format
);
166 vfprintf(ipt_file
, format
, args
);
170 void ip6t_write(const char *format
, ...)
175 va_start(args
, format
);
176 vfprintf(ip6t_file
, format
, args
);
181 // -----------------------------------------------------------------------------
183 int ipt_dscp(const char *v
, char *opt
)
192 n
= strtoul(v
, NULL
, 0);
194 sprintf(opt
, " -m dscp --dscp 0x%02X", n
);
199 modprobe("ipt_dscp");
204 // -----------------------------------------------------------------------------
207 int ipt_ipp2p(const char *v
, char *opt
)
216 strcpy(opt
, "-m ipp2p ");
217 if ((n
& 0xFFF) == 0xFFF) {
218 strcat(opt
, "--ipp2p");
222 if (n
& 0x0001) strcat(opt
, "--apple ");
223 if (n
& 0x0002) strcat(opt
, "--ares ");
224 if (n
& 0x0004) strcat(opt
, "--bit ");
225 if (n
& 0x0008) strcat(opt
, "--dc ");
226 if (n
& 0x0010) strcat(opt
, "--edk ");
227 if (n
& 0x0020) strcat(opt
, "--gnu ");
228 if (n
& 0x0040) strcat(opt
, "--kazaa ");
229 if (n
& 0x0080) strcat(opt
, "--mute ");
230 if (n
& 0x0100) strcat(opt
, "--soul ");
231 if (n
& 0x0200) strcat(opt
, "--waste ");
232 if (n
& 0x0400) strcat(opt
, "--winmx ");
233 if (n
& 0x0800) strcat(opt
, "--xdcc ");
236 modprobe("ipt_ipp2p");
241 // -----------------------------------------------------------------------------
246 // This L7 matches inbound traffic, caches the results, then the L7 outbound
247 // should read the cached result and set the appropriate marks -- zzz
248 void ipt_layer7_inbound(void)
253 if (!layer7_in
) return;
255 en
= nvram_match("nf_l7in", "1");
257 ipt_write(":L7in - [0:0]\n");
258 for (i
= 0; i
< wanfaces
.count
; ++i
) {
259 if (*(wanfaces
.iface
[i
].name
)) {
260 ipt_write("-A FORWARD -i %s -j L7in\n",
261 wanfaces
.iface
[i
].name
);
268 if (en
) ipt_write("-A L7in %s -j RETURN\n", *p
);
276 int ipt_layer7(const char *v
, char *opt
)
282 if (*v
== 0) return 0;
283 if (strlen(v
) > 32) return -1;
285 path
= "/etc/l7-extra";
286 sprintf(s
, "%s/%s.pat", path
, v
);
288 path
= "/etc/l7-protocols";
289 sprintf(s
, "%s/%s.pat", path
, v
);
291 syslog(LOG_ERR
, "L7 %s was not found", v
);
296 sprintf(opt
, "-m layer7 --l7dir %s --l7proto %s", path
, v
);
298 if (nvram_match("nf_l7in", "1")) {
299 if (!layer7_in
) layer7_in
= calloc(51, sizeof(char *));
305 if (strcmp(*p
, opt
) == 0) return 1;
308 if (((p
- layer7_in
) / sizeof(char *)) < 50) *p
= strdup(opt
);
313 modprobe("xt_layer7");
315 modprobe("ipt_layer7");
321 // -----------------------------------------------------------------------------
323 static void save_webmon(void)
325 system("cp /proc/webmon_recent_domains /var/webmon/domain");
326 system("cp /proc/webmon_recent_searches /var/webmon/search");
329 static void ipt_webmon(int do_ip6t
)
331 int wmtype
, clear
, i
;
336 if (!nvram_get_int("log_wm")) return;
337 wmtype
= nvram_get_int("log_wmtype");
338 clear
= nvram_get_int("log_wmclear");
340 ip46t_cond_write(do_ip6t
, ":monitor - [0:0]\n");
343 // TODO: check for the IP address type (v4/v6)
344 // (currently IPv6 source addresses are not filtered)
346 ip6t_write("-A FORWARD -o %s -j monitor\n", wan6face
);
350 strlcpy(t
, wmtype
== 1 ? nvram_safe_get("log_wmip") : "", sizeof(t
));
353 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
356 for (i
= 0; i
< wanfaces
.count
; ++i
) {
357 if (*(wanfaces
.iface
[i
].name
)) {
358 ipt_write("-A FORWARD -o %s %s -j monitor\n",
359 wanfaces
.iface
[i
].name
, src
);
371 if (wmtype
== 2 && !do_ip6t
) {
372 strlcpy(t
, nvram_safe_get("log_wmip"), sizeof(t
));
375 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
377 if (*src
) ipt_write("-A monitor %s -j RETURN\n", src
);
383 ip46t_cond_write(do_ip6t
,
384 "-A monitor -p tcp -m webmon "
385 "--max_domains %d --max_searches %d %s %s -j RETURN\n",
386 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
387 (clear
& 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
388 (clear
& 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
391 modprobe("xt_webmon");
393 modprobe("ipt_webmon");
398 // -----------------------------------------------------------------------------
400 // -----------------------------------------------------------------------------
402 static void mangle_table(void)
409 ":PREROUTING ACCEPT [0:0]\n"
410 ":OUTPUT ACCEPT [0:0]\n");
416 p
= nvram_safe_get("nf_ttl");
417 if (strncmp(p
, "c:", 2) == 0) {
420 p
= (ttl
>= 0 && ttl
<= 255) ? "set" : NULL
;
422 else if ((ttl
= atoi(p
)) != 0) {
430 if (ttl
> 255) p
= NULL
;
440 // set TTL on primary WAN iface only
441 wanface
= wanfaces
.iface
[0].name
;
443 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
444 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
450 ip46t_write("COMMIT\n");
455 // -----------------------------------------------------------------------------
457 // -----------------------------------------------------------------------------
459 static void nat_table(void)
470 ":PREROUTING ACCEPT [0:0]\n"
471 ":POSTROUTING ACCEPT [0:0]\n"
472 ":OUTPUT ACCEPT [0:0]\n"
474 chain_wan_prerouting
);
477 strlcpy(lanaddr
, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr
));
478 strlcpy(lanmask
, nvram_safe_get("lan_netmask"), sizeof(lanmask
));
480 for (i
= 0; i
< wanfaces
.count
; ++i
) {
481 if (*(wanfaces
.iface
[i
].name
)) {
482 // chain_wan_prerouting
484 ipt_write("-A PREROUTING -d %s -j %s\n",
485 wanfaces
.iface
[i
].ip
, chain_wan_prerouting
);
487 // Drop incoming packets which destination IP address is to our LAN side directly
488 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
489 wanfaces
.iface
[i
].name
,
490 lanaddr
, lanmask
); // note: ipt will correct lanaddr
495 if (nvram_match("dns_intcpt", "1")) {
496 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
502 // ICMP packets are always redirected to INPUT chains
503 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting
, lanaddr
);
505 ipt_forward(IPT_TABLE_NAT
);
506 ipt_triggered(IPT_TABLE_NAT
);
509 if (nvram_get_int("upnp_enable") & 3) {
510 ipt_write(":upnp - [0:0]\n");
512 // ! for loopback (all) to work
513 ipt_write("-A %s -j upnp\n", chain_wan_prerouting
);
516 for (i
= 0; i
< wanfaces
.count
; ++i
) {
517 if (*(wanfaces
.iface
[i
].name
)) {
518 ipt_write("-A PREROUTING -i %s -j upnp\n", wanfaces
.iface
[i
].name
);
526 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
529 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
531 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting
, src
, dst
);
540 switch (get_ipv6_service()) {
542 // avoid NATing proto-41 packets when using 6in4 tunnel
548 for (i
= 0; i
< wanfaces
.count
; ++i
) {
549 if (*(wanfaces
.iface
[i
].name
)) {
550 if ((!wanup
) || (nvram_get_int("net_snat") != 1))
551 ipt_write("-A POSTROUTING %s -o %s -j MASQUERADE\n", p
, wanfaces
.iface
[i
].name
);
553 ipt_write("-A POSTROUTING %s -o %s -j SNAT --to-source %s\n", p
, wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].ip
);
557 switch (nvram_get_int("nf_loopback")) {
558 case 1: // 1 = forwarded-only
559 case 2: // 2 = disable
561 default: // 0 = all (same as block_loopback=0)
562 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
570 ipt_write("COMMIT\n");
573 // -----------------------------------------------------------------------------
575 // -----------------------------------------------------------------------------
577 static void filter_input(void)
587 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
588 for (n
= 0; n
< wanfaces
.count
; ++n
) {
589 if (*(wanfaces
.iface
[n
].name
)) {
590 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanfaces
.iface
[n
].ip
);
596 "-A INPUT -m state --state INVALID -j %s\n"
597 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
601 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
602 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
604 ? what if the user uses the start button in GUI ?
605 if (nvram_get_int("telnetd_eas"))
606 if (nvram_get_int("sshd_eas"))
609 modprobe("xt_recent");
611 modprobe("ipt_recent");
616 "-A shlimit -m recent --set --name shlimit\n"
617 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
618 atoi(hit
) + 1, sec
, chain_in_drop
);
621 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
622 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
623 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
626 if (n
& 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
630 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
631 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
633 modprobe("xt_recent");
635 modprobe("ipt_recent");
640 "-A ftplimit -m recent --set --name ftp\n"
641 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
642 atoi(hit
) + 1, sec
, chain_in_drop
);
643 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
648 "-A INPUT -i %s -j ACCEPT\n"
649 "-A INPUT -i lo -j ACCEPT\n",
653 switch (get_ipv6_service()) {
655 // Accept ICMP requests from the remote tunnel endpoint
656 if ((p
= nvram_get("ipv6_tun_v4end")) && *p
&& strcmp(p
, "0.0.0.0") != 0)
657 ipt_write("-A INPUT -p icmp -s %s -j %s\n", p
, chain_in_accept
);
658 ipt_write("-A INPUT -p 41 -j %s\n", chain_in_accept
);
663 // ICMP request from WAN interface
664 if (nvram_match("block_wan", "0")) {
665 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
666 ipt_write("-A INPUT -p icmp -m limit --limit 1/second -j %s\n", chain_in_accept
);
667 // allow udp traceroute packets
668 ipt_write("-A INPUT -p udp -m udp --dport 33434:33534 -m limit --limit 5/second -j %s\n", chain_in_accept
);
671 /* Accept incoming packets from broken dhcp servers, which are sending replies
672 * from addresses other than used for query. This could lead to a lower level
673 * of security, so allow to disable it via nvram variable.
675 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
676 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept
);
679 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
682 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
687 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
688 s
, nvram_safe_get("http_wanport"), chain_in_accept
);
691 if (nvram_get_int("sshd_remote")) {
692 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
693 s
, nvram_safe_get("sshd_rport"), chain_in_accept
);
701 #ifdef TCONFIG_FTP // !!TB - FTP Server
702 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
703 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
706 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
709 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
710 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
718 // IGMP query from WAN interface
719 if (nvram_match("multicast_pass", "1")) {
720 ipt_write("-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT\n");
721 ipt_write("-A INPUT -p udp -d 224.0.0.0/4 ! --dport 1900 -j ACCEPT\n");
724 // Routing protocol, RIP, accept
725 if (nvram_invmatch("dr_wan_rx", "0")) {
726 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
730 if (*chain_in_drop
== 'l') {
731 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
734 // default policy: DROP
737 // clamp TCP MSS to PMTU of WAN interface
738 static void clampmss(void)
741 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
743 int rmtu
= nvram_get_int("wan_run_mtu");
744 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
746 ipt_write("--clamp-mss-to-pmtu\n");
749 ipt_write("--set-mss %d\n", rmtu
- 40);
754 static void filter_forward(void)
763 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
764 "-A FORWARD -m state --state INVALID -j DROP\n", // drop if INVALID state
767 // clamp tcp mss to pmtu
772 ipt_layer7_inbound();
780 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"); // already established or related (via helper)
782 for (i
= 0; i
< wanfaces
.count
; ++i
) {
783 if (*(wanfaces
.iface
[i
].name
)) {
785 "-A FORWARD -i %s -j wanin\n" // generic from wan
786 "-A FORWARD -o %s -j wanout\n", // generic to wan
787 wanfaces
.iface
[i
].name
, wanfaces
.iface
[i
].name
);
791 ipt_write("-A FORWARD -i %s -j %s\n", // from lan
792 lanface
, chain_out_accept
);
794 if (nvram_get_int("upnp_enable") & 3) {
795 ipt_write(":upnp - [0:0]\n");
796 for (i
= 0; i
< wanfaces
.count
; ++i
) {
797 if (*(wanfaces
.iface
[i
].name
)) {
798 ipt_write("-A FORWARD -i %s -j upnp\n",
799 wanfaces
.iface
[i
].name
);
805 if (nvram_match("multicast_pass", "1")) {
806 ipt_write("-A wanin -p udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
808 ipt_triggered(IPT_TABLE_FILTER
);
809 ipt_forward(IPT_TABLE_FILTER
);
812 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
815 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
817 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
825 // default policy: DROP
828 static void filter_log(void)
833 n
= nvram_get_int("log_limit");
834 if ((n
>= 1) && (n
<= 9999)) {
835 sprintf(limit
, "-m limit --limit %d/m", n
);
842 modprobe("ip6t_LOG");
844 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
847 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
848 "-A logdrop -j DROP\n"
849 ":logreject - [0:0]\n"
850 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
851 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
854 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
856 ":logaccept - [0:0]\n"
857 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
858 "-A logaccept -j ACCEPT\n",
864 static void filter6_input(void)
873 "-A INPUT -m rt --rt-type 0 -j %s\n"
874 /* "-A INPUT -m state --state INVALID -j %s\n" */
875 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
876 chain_in_drop
/*, chain_in_drop*/);
879 modprobe("xt_length");
880 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
883 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
884 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
886 modprobe("xt_recent");
888 modprobe("ipt_recent");
893 "-A shlimit -m recent --set --name shlimit\n"
894 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
895 atoi(hit
) + 1, sec
, chain_in_drop
);
898 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface
, nvram_safe_get("sshd_port"));
899 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
900 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
903 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"));
907 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
908 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
910 modprobe("xt_recent");
912 modprobe("ipt_recent");
917 "-A ftplimit -m recent --set --name ftp\n"
918 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
919 atoi(hit
) + 1, sec
, chain_in_drop
);
920 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
922 #endif // TCONFIG_FTP
925 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
926 "-A INPUT -i lo -j ACCEPT\n",
929 switch (get_ipv6_service()) {
930 case IPV6_NATIVE_DHCP
:
931 // allow responses from the dhcpv6 server
932 ip6t_write("-A INPUT -p udp --dport 546 -j %s\n", chain_in_accept
);
937 const int allowed_icmpv6
[6] = { 1, 2, 3, 4, 128, 129 };
938 for (n
= 0; n
< sizeof(allowed_icmpv6
)/sizeof(int); n
++) {
939 ip6t_write("-A INPUT -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[n
], chain_in_accept
);
943 // TODO: create list for allowed remote ipv6 addresses?
944 // Currently: disabled if there is a non-empty list of allowed ipv4 addresses,
945 // otherwise unrestricted
946 if (strlen(nvram_safe_get("rmgt_sip")) == 0) {
948 ip6t_write("-A INPUT -p tcp -m tcp --dport %s -j %s\n",
949 nvram_safe_get("http_wanport"), chain_in_accept
);
952 if (nvram_get_int("sshd_remote")) {
953 ip6t_write("-A INPUT -p tcp -m tcp --dport %s -j %s\n",
954 nvram_safe_get("sshd_rport"), chain_in_accept
);
959 // TODO: create list for allowed remote ipv6 addresses? (see above)...
961 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
962 if (strlen(nvram_safe_get("ftp_sip")) == 0) {
963 ip6t_write("-A INPUT -p tcp -m tcp --dport %s -j %s\n",
964 nvram_safe_get("ftp_port"), chain_in_accept
);
970 if (*chain_in_drop
== 'l') {
971 ip6t_write( "-A INPUT -j %s\n", chain_in_drop
);
974 // default policy: DROP
977 static void filter6_forward(void)
982 "-A FORWARD -m rt --rt-type 0 -j DROP\n"
983 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
984 /*"-A FORWARD -m state --state INVALID -j DROP\n"*/, // drop if INVALID state
987 // Filter out invalid WAN->WAN connections
988 ip6t_write("-A FORWARD -o %s ! -i %s -j %s\n", wan6face
, lanface
, chain_in_drop
);
991 modprobe("xt_length");
992 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
995 // clamp tcp mss to pmtu TODO?
998 // TODO: support l7, access restrictions on ipv6?
1002 ipt_layer7_inbound();
1012 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
1013 "-A FORWARD -i %s -j wanin\n" // generic from wan
1014 "-A FORWARD -o %s -j wanout\n" // generic to wan
1015 "-A FORWARD -i %s -j %s\n", // from lan
1016 wan6face
, wan6face
, lanface
, chain_out_accept
);
1019 const int allowed_icmpv6
[6] = { 1, 2, 3, 4, 128, 129 };
1020 for (n
= 0; n
< sizeof(allowed_icmpv6
)/sizeof(int); n
++) {
1021 ip6t_write("-A FORWARD -p ipv6-icmp --icmpv6-type %i -j %s\n", allowed_icmpv6
[n
], chain_in_accept
);
1025 //ipt_triggered(IPT_TABLE_FILTER);
1029 // default policy: DROP
1034 static void filter_table(void)
1038 ":INPUT DROP [0:0]\n"
1039 ":OUTPUT ACCEPT [0:0]\n"
1047 ip6t_write("-A OUTPUT -m rt --rt-type 0 -j %s\n", chain_in_drop
);
1050 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
1051 ip46t_write(":FORWARD DROP [0:0]\n");
1058 ip46t_write(":FORWARD ACCEPT [0:0]\n");
1061 ip46t_write("COMMIT\n");
1065 // -----------------------------------------------------------------------------
1067 int start_firewall(void)
1070 struct dirent
*dirent
;
1075 char *iptrestore_argv
[] = { "iptables-restore", (char *)ipt_fname
, NULL
};
1077 char *ip6trestore_argv
[] = { "ip6tables-restore", (char *)ip6t_fname
, NULL
};
1080 simple_lock("firewall");
1081 simple_lock("restrictions");
1083 wanproto
= get_wan_proto();
1084 wanup
= check_wanup();
1086 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
1088 /* NAT performance tweaks
1089 * These values can be overriden later if needed via firewall script
1091 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
1092 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
1093 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
1094 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
1095 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
1096 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
1097 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
1098 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1099 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1100 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1101 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1102 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1104 /* DoS-related tweaks */
1105 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1106 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1107 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1110 /* Force IGMPv2 due EMF limitations */
1111 if (nvram_get_int("emf_enable")) {
1112 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1113 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1117 n
= nvram_get_int("log_in");
1118 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
1119 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1121 n
= nvram_get_int("log_out");
1122 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
1123 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1124 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
1126 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1128 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
1130 memcpy(&wanfaces
, get_wanfaces(), sizeof(wanfaces
));
1131 wanface
= wanfaces
.iface
[0].name
;
1133 strlcpy(wan6face
, get_wan6face(), sizeof(wan6face
));
1136 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
1137 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
1138 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
1141 block obviously spoofed IP addresses
1144 1 - do source validation by reversed path, as specified in RFC1812
1145 Recommended option for single homed hosts and stub network
1146 routers. Could cause troubles for complicated (not loop free)
1147 networks running a slow unreliable protocol (sort of RIP),
1148 or using static routes.
1149 0 - No source validation.
1151 c
= nvram_get("wan_ifname");
1152 /* mcast needs rp filter to be turned off only for non default iface */
1153 if (!(nvram_match("multicast_pass", "1")) || strcmp(wanface
, c
) == 0) c
= NULL
;
1155 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
1156 while ((dirent
= readdir(dir
)) != NULL
) {
1157 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
1158 f_write_string(s
, (c
&& strcmp(dirent
->d_name
, c
) == 0) ? "0" : "1", 0, 0);
1164 gateway_mode
= !nvram_match("wk_mode", "router");
1166 /* Remote management */
1167 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1168 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
1171 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
1172 notice_set("iptables", "Unable to create iptables restore file");
1173 simple_unlock("firewall");
1178 if ((ip6t_file
= fopen(ip6t_fname
, "w")) == NULL
) {
1179 notice_set("ip6tables", "Unable to create ip6tables restore file");
1180 simple_unlock("firewall");
1183 modprobe("nf_conntrack_ipv6");
1184 modprobe("ip6t_REJECT");
1199 #ifdef DEBUG_IPTFILE
1201 simple_unlock("firewall");
1202 simple_unlock("restrictions");
1209 if (nvram_get_int("upnp_enable") & 3) {
1210 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
1211 if (killall("miniupnpd", SIGUSR2
) == 0) {
1212 f_wait_notexists("/etc/upnp/save", 5);
1216 notice_set("iptables", "");
1217 if (_eval(iptrestore_argv
, ">/var/notice/iptables", 0, NULL
) == 0) {
1219 notice_set("iptables", "");
1222 sprintf(s
, "%s.error", ipt_fname
);
1223 rename(ipt_fname
, s
);
1224 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1231 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1232 -A INPUT -i br0 -j ACCEPT
1236 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1237 -A FORWARD -i br0 -j ACCEPT
1243 if (ipv6_enabled()) {
1244 notice_set("ip6tables", "");
1245 if (_eval(ip6trestore_argv
, ">/var/notice/ip6tables", 0, NULL
) == 0) {
1247 notice_set("ip6tables", "");
1250 sprintf(s
, "%s.error", ip6t_fname
);
1251 rename(ip6t_fname
, s
);
1252 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
1258 if (nvram_get_int("upnp_enable") & 3) {
1259 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
1260 killall("miniupnpd", SIGUSR2
);
1263 simple_unlock("restrictions");
1264 sched_restrictions();
1265 enable_ip_forward();
1267 led(LED_DMZ
, dmz_dst(NULL
));
1270 modprobe_r("nf_conntrack_ipv6");
1271 modprobe_r("ip6t_LOG");
1272 modprobe_r("ip6t_REJECT");
1275 modprobe_r("xt_layer7");
1276 modprobe_r("xt_recent");
1277 modprobe_r("xt_HL");
1278 modprobe_r("xt_length");
1279 modprobe_r("xt_web");
1280 modprobe_r("xt_webmon");
1281 modprobe_r("xt_dscp");
1283 modprobe_r("ipt_layer7");
1284 modprobe_r("ipt_recent");
1285 modprobe_r("ipt_TTL");
1286 modprobe_r("ipt_web");
1287 modprobe_r("ipt_webmon");
1288 modprobe_r("ipt_dscp");
1290 modprobe_r("ipt_ipp2p");
1292 unlink("/var/webmon/domain");
1293 unlink("/var/webmon/search");
1295 #ifdef TCONFIG_OPENVPN
1296 run_vpn_firewall_scripts();
1298 run_nvscript("script_fire", NULL
, 1);
1300 simple_unlock("firewall");
1304 int stop_firewall(void)
1310 #ifdef DEBUG_IPTFILE
1311 void create_test_iptfile(void)