rc: Couple small fixes to IPv6 firewall
[tomato.git] / release / src / router / rc / firewall.c
blob9a666b3713d9201c7e4adcf9fc7e6b3e8a8586cd
1 /*
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
26 #include "rc.h"
28 #include <stdarg.h>
29 #include <arpa/inet.h>
30 #include <dirent.h>
32 char wanface[IFNAMSIZ + 1];
33 char manface[IFNAMSIZ + 1];
34 char lanface[IFNAMSIZ + 1];
35 #ifdef TCONFIG_IPV6
36 char wan6face[IFNAMSIZ + 1];
37 #endif
38 char wanaddr[sizeof("xxx.xxx.xxx.xxx") + 1];
39 char manaddr[sizeof("xxx.xxx.xxx.xxx") + 1];
40 char lan_cclass[sizeof("xxx.xxx.xxx.") + 1];
41 static int web_lanport;
43 #ifdef DEBUG_IPTFILE
44 static int debug_only = 0;
45 #endif
47 static int gateway_mode;
48 static int remotemanage;
49 static int wanup;
51 const char *chain_in_drop;
52 const char *chain_in_accept;
53 const char *chain_out_drop;
54 const char *chain_out_accept;
55 const char *chain_out_reject;
57 const char chain_wan_prerouting[] = "WANPREROUTING";
58 const char ipt_fname[] = "/etc/iptables";
59 FILE *ipt_file;
61 #ifdef TCONFIG_IPV6
62 const char ip6t_fname[] = "/etc/ip6tables";
63 FILE *ip6t_file;
64 #endif
68 struct {
69 } firewall_data;
72 // -----------------------------------------------------------------------------
75 void enable_ip_forward(void)
78 ip_forward - BOOLEAN
79 0 - disabled (default)
80 not 0 - enabled
82 Forward Packets between interfaces.
84 This variable is special, its change resets all configuration
85 parameters to their default state (RFC1122 for hosts, RFC1812
86 for routers)
88 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
92 // -----------------------------------------------------------------------------
95 static int ip2cclass(char *ipaddr, char *new, int count)
97 int ip[4];
99 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
100 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
105 static int dmz_dst(char *s)
107 struct in_addr ia;
108 char *p;
109 int n;
111 if (nvram_get_int("dmz_enable") <= 0) return 0;
113 p = nvram_safe_get("dmz_ipaddr");
114 if ((ia.s_addr = inet_addr(p)) == (in_addr_t)-1) {
115 if (((n = atoi(p)) <= 0) || (n >= 255)) return 0;
116 if (s) sprintf(s, "%s%d", lan_cclass, n);
117 return 1;
120 if (s) strcpy(s, inet_ntoa(ia));
121 return 1;
124 void ipt_addr(char *addr, int maxlen, const char *s, const char *dir)
126 char p[32];
128 if ((*s) && (*dir))
130 if (sscanf(s, "%[0-9.]-%[0-9.]", p, p) == 2)
131 snprintf(addr, maxlen, "-m iprange --%s-range %s", dir, s);
132 else
133 snprintf(addr, maxlen, "-%c %s", dir[0], s);
135 else
136 *addr = 0;
139 static inline void ipt_source(const char *s, char *src)
141 ipt_addr(src, 64, s, "src");
145 static void get_src(const char *nv, char *src)
147 char *p;
149 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
150 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
152 else {
153 *src = 0;
158 void ipt_write(const char *format, ...)
160 va_list args;
162 va_start(args, format);
163 vfprintf(ipt_file, format, args);
164 va_end(args);
167 void ip6t_write(const char *format, ...)
169 #ifdef TCONFIG_IPV6
170 va_list args;
172 va_start(args, format);
173 vfprintf(ip6t_file, format, args);
174 va_end(args);
175 #endif
178 // -----------------------------------------------------------------------------
181 int ipt_ipp2p(const char *v, char *opt)
183 int n = atoi(v);
185 if (n == 0) {
186 *opt = 0;
187 return 0;
190 strcpy(opt, "-m ipp2p ");
191 if ((n & 0xFFF) == 0xFFF) {
192 strcat(opt, "--ipp2p");
194 else {
195 // x12
196 if (n & 0x0001) strcat(opt, "--apple ");
197 if (n & 0x0002) strcat(opt, "--ares ");
198 if (n & 0x0004) strcat(opt, "--bit ");
199 if (n & 0x0008) strcat(opt, "--dc ");
200 if (n & 0x0010) strcat(opt, "--edk ");
201 if (n & 0x0020) strcat(opt, "--gnu ");
202 if (n & 0x0040) strcat(opt, "--kazaa ");
203 if (n & 0x0080) strcat(opt, "--mute ");
204 if (n & 0x0100) strcat(opt, "--soul ");
205 if (n & 0x0200) strcat(opt, "--waste ");
206 if (n & 0x0400) strcat(opt, "--winmx ");
207 if (n & 0x0800) strcat(opt, "--xdcc ");
210 modprobe("ipt_ipp2p");
211 return 1;
215 // -----------------------------------------------------------------------------
218 char **layer7_in;
220 // This L7 matches inbound traffic, caches the results, then the L7 outbound
221 // should read the cached result and set the appropriate marks -- zzz
222 void ipt_layer7_inbound(void)
224 int en;
225 char **p;
227 if (!layer7_in) return;
229 en = nvram_match("nf_l7in", "1");
230 if (en) {
231 ipt_write(
232 ":L7in - [0:0]\n"
233 "-A FORWARD -i %s -j L7in\n",
234 wanface);
235 if (*manface)
236 ipt_write(
237 "-A FORWARD -i %s -j L7in\n",
238 manface);
241 p = layer7_in;
242 while (*p) {
243 if (en) ipt_write("-A L7in %s -j RETURN\n", *p);
244 free(*p);
245 ++p;
247 free(layer7_in);
248 layer7_in = NULL;
251 int ipt_layer7(const char *v, char *opt)
253 char s[128];
254 char *path;
256 *opt = 0;
257 if (*v == 0) return 0;
258 if (strlen(v) > 32) return -1;
260 path = "/etc/l7-extra";
261 sprintf(s, "%s/%s.pat", path, v);
262 if (!f_exists(s)) {
263 path = "/etc/l7-protocols";
264 sprintf(s, "%s/%s.pat", path, v);
265 if (!f_exists(s)) {
266 syslog(LOG_ERR, "L7 %s was not found", v);
267 return -1;
271 sprintf(opt, "-m layer7 --l7dir %s --l7proto %s", path, v);
273 if (nvram_match("nf_l7in", "1")) {
274 if (!layer7_in) layer7_in = calloc(51, sizeof(char *));
275 if (layer7_in) {
276 char **p;
278 p = layer7_in;
279 while (*p) {
280 if (strcmp(*p, opt) == 0) return 1;
281 ++p;
283 if (((p - layer7_in) / sizeof(char *)) < 50) *p = strdup(opt);
287 #ifdef LINUX26
288 modprobe("xt_layer7");
289 #else
290 modprobe("ipt_layer7");
291 #endif
292 return 1;
296 // -----------------------------------------------------------------------------
298 static void save_webmon(void)
300 system("cp /proc/webmon_recent_domains /var/webmon/domain");
301 system("cp /proc/webmon_recent_searches /var/webmon/search");
304 static void ipt_webmon(void)
306 int wmtype, clear;
308 if (!nvram_get_int("log_wm")) return;
309 wmtype = nvram_get_int("log_wmtype");
310 clear = nvram_get_int("log_wmclear");
312 ipt_write(
313 ":monitor - [0:0]\n"
314 "-A FORWARD -o %s -j monitor\n",
315 wanface);
316 if (*manface)
317 ipt_write(
318 "-A FORWARD -o %s -j monitor\n",
319 manface);
321 ipt_write(
322 "-A monitor -m webmon "
323 "--max_domains %d --max_searches %d %s%s %s %s\n",
324 nvram_get_int("log_wmdmax") ? : 1, nvram_get_int("log_wmsmax") ? : 1,
325 wmtype == 1 ? "--include_ips " : wmtype == 2 ? "--exclude_ips " : "",
326 wmtype == 0 ? "" : nvram_safe_get("log_wmip"),
327 (clear & 1) == 0 ? "--domain_load_file /var/webmon/domain" : "--clear_domain",
328 (clear & 2) == 0 ? "--search_load_file /var/webmon/search" : "--clear_search");
330 modprobe("ipt_webmon");
334 // -----------------------------------------------------------------------------
335 // MANGLE
336 // -----------------------------------------------------------------------------
338 static void mangle_table(void)
340 int ttl;
341 char *p;
343 ip46t_write(
344 "*mangle\n"
345 ":PREROUTING ACCEPT [0:0]\n"
346 ":OUTPUT ACCEPT [0:0]\n");
348 if (wanup) {
350 ipt_qos();
352 p = nvram_safe_get("nf_ttl");
353 if (strncmp(p, "c:", 2) == 0) {
354 p += 2;
355 ttl = atoi(p);
356 p = (ttl >= 0 && ttl <= 255) ? "set" : NULL;
358 else if ((ttl = atoi(p)) != 0) {
359 if (ttl > 0) {
360 p = "inc";
362 else {
363 ttl = -ttl;
364 p = "dec";
366 if (ttl > 255) p = NULL;
368 else p = NULL;
370 if (p) {
371 #ifdef LINUX26
372 modprobe("xt_HL");
373 #else
374 modprobe("ipt_TTL");
375 #endif
376 ip46t_write(
377 "-I PREROUTING -i %s -j TTL --ttl-%s %d\n"
378 "-I POSTROUTING -o %s -j TTL --ttl-%s %d\n",
379 wanface, p, ttl,
380 wanface, p, ttl);
384 ip46t_write("COMMIT\n");
389 // -----------------------------------------------------------------------------
390 // NAT
391 // -----------------------------------------------------------------------------
393 static void nat_table(void)
395 char lanaddr[32];
396 char lanmask[32];
397 char dst[64];
398 char src[64];
399 char t[512];
400 char *p, *c;
402 ipt_write("*nat\n"
403 ":PREROUTING ACCEPT [0:0]\n"
404 ":POSTROUTING ACCEPT [0:0]\n"
405 ":OUTPUT ACCEPT [0:0]\n"
406 ":%s - [0:0]\n",
407 chain_wan_prerouting);
409 if (gateway_mode) {
410 strlcpy(lanaddr, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr));
411 strlcpy(lanmask, nvram_safe_get("lan_netmask"), sizeof(lanmask));
413 // chain_wan_prerouting
414 if (wanup)
415 ipt_write("-A PREROUTING -d %s -j %s\n", wanaddr, chain_wan_prerouting);
416 if (*manaddr)
417 ipt_write("-A PREROUTING -d %s -j %s\n", manaddr, chain_wan_prerouting);
419 // Drop incoming packets which destination IP address is to our LAN side directly
420 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
421 wanface,
422 lanaddr, lanmask); // note: ipt will correct lanaddr
423 if (*manface)
424 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
425 manface,
426 lanaddr, lanmask); // note: ipt will correct lanaddr
428 if (wanup) {
429 if (nvram_match("dns_intcpt", "1")) {
430 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
431 lanaddr, lanmask,
432 lanaddr, lanmask,
433 lanaddr);
436 // ICMP packets are always redirected to INPUT chains
437 ipt_write("-A %s -p icmp -j DNAT --to-destination %s\n", chain_wan_prerouting, lanaddr);
439 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
440 p = t;
441 do {
442 if ((c = strchr(p, ',')) != NULL) *c = 0;
443 ipt_source(p, src);
445 if (remotemanage) {
446 ipt_write("-A %s -p tcp -m tcp %s --dport %s -j DNAT --to-destination %s:%d\n",
447 chain_wan_prerouting,
448 src,
449 nvram_safe_get("http_wanport"),
450 lanaddr, web_lanport);
452 if (nvram_get_int("sshd_remote")) {
453 ipt_write("-A %s %s -p tcp -m tcp --dport %s -j DNAT --to-destination %s:%s\n",
454 chain_wan_prerouting,
455 src,
456 nvram_safe_get("sshd_rport"),
457 lanaddr, nvram_safe_get("sshd_port"));
460 if (!c) break;
461 p = c + 1;
462 } while (*p);
464 ipt_forward(IPT_TABLE_NAT);
465 ipt_triggered(IPT_TABLE_NAT);
468 if (nvram_get_int("upnp_enable") & 3) {
469 ipt_write(":upnp - [0:0]\n");
470 if (wanup) {
471 // ! for loopback (all) to work
472 ipt_write("-A %s -j upnp\n", chain_wan_prerouting);
474 else {
475 ipt_write("-A PREROUTING -i %s -j upnp\n", wanface);
476 if (*manface)
477 ipt_write("-A PREROUTING -i %s -j upnp\n", manface);
481 if (wanup) {
482 if (dmz_dst(dst)) {
483 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
484 p = t;
485 do {
486 if ((c = strchr(p, ',')) != NULL) *c = 0;
487 ipt_source(p, src);
488 ipt_write("-A %s %s -j DNAT --to-destination %s\n", chain_wan_prerouting, src, dst);
489 if (!c) break;
490 p = c + 1;
491 } while (*p);
495 if ((!wanup) || (nvram_get_int("net_snat") != 1)) {
496 ipt_write("-A POSTROUTING -o %s -j MASQUERADE\n", wanface);
497 if (*manface)
498 ipt_write("-A POSTROUTING -o %s -j MASQUERADE\n", manface);
500 else {
501 ipt_write("-A POSTROUTING -o %s -j SNAT --to-source %s\n", wanface, wanaddr);
502 if (*manface && *manaddr)
503 ipt_write("-A POSTROUTING -o %s -j SNAT --to-source %s\n", manface, manaddr);
506 switch (nvram_get_int("nf_loopback")) {
507 case 1: // 1 = forwarded-only
508 case 2: // 2 = disable
509 break;
510 default: // 0 = all (same as block_loopback=0)
511 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
512 lanface,
513 lanaddr, lanmask,
514 lanaddr, lanmask,
515 lanaddr);
516 break;
519 ipt_write("COMMIT\n");
522 // -----------------------------------------------------------------------------
523 // FILTER
524 // -----------------------------------------------------------------------------
526 static void filter_input(void)
528 char s[64];
529 char t[512];
530 char *en;
531 char *sec;
532 char *hit;
533 int n;
534 char *p, *c;
536 if ((nvram_get_int("nf_loopback") != 0) && (wanup)) { // 0 = all
537 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, wanaddr);
538 if (*manaddr)
539 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface, manaddr);
542 ipt_write(
543 "-A INPUT -m state --state INVALID -j %s\n"
544 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
545 chain_in_drop);
548 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
549 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
551 ? what if the user uses the start button in GUI ?
552 if (nvram_get_int("telnetd_eas"))
553 if (nvram_get_int("sshd_eas"))
555 #ifdef LINUX26
556 modprobe("xt_recent");
557 #else
558 modprobe("ipt_recent");
559 #endif
561 ipt_write(
562 "-N shlimit\n"
563 "-A shlimit -m recent --set --name shlimit\n"
564 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
565 atoi(hit) + 1, sec, chain_in_drop);
567 if (n & 1) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
568 if (n & 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
571 #ifdef TCONFIG_FTP
572 strlcpy(s, nvram_safe_get("ftp_limit"), sizeof(s));
573 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && (atoi(en)) && (nvram_get_int("ftp_enable") == 1)) {
574 #ifdef LINUX26
575 modprobe("xt_recent");
576 #else
577 modprobe("ipt_recent");
578 #endif
580 ipt_write(
581 "-N ftplimit\n"
582 "-A ftplimit -m recent --set --name ftp\n"
583 "-A ftplimit -m recent --update --hitcount %d --seconds %s --name ftp -j %s\n",
584 atoi(hit) + 1, sec, chain_in_drop);
585 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
587 #endif
589 ipt_write(
590 "-A INPUT -i %s -j ACCEPT\n"
591 "-A INPUT -i lo -j ACCEPT\n",
592 lanface);
594 // ICMP request from WAN interface
595 if (nvram_match("block_wan", "0")) {
596 // allow ICMP packets to be received, but restrict the flow to avoid ping flood attacks
597 ipt_write("-A INPUT -p icmp -m limit --limit 1/second -j %s\n", chain_in_accept);
598 // allow udp traceroute packets
599 ipt_write("-A INPUT -p udp -m udp --dport 33434:33534 -m limit --limit 5/second -j %s\n", chain_in_accept);
602 /* Accept incoming packets from broken dhcp servers, which are sending replies
603 * from addresses other than used for query. This could lead to a lower level
604 * of security, so allow to disable it via nvram variable.
606 if (nvram_invmatch("dhcp_pass", "0") && using_dhcpc()) {
607 ipt_write("-A INPUT -p udp --sport 67 --dport 68 -j %s\n", chain_in_accept);
610 strlcpy(t, nvram_safe_get("rmgt_sip"), sizeof(t));
611 p = t;
612 do {
613 if ((c = strchr(p, ',')) != NULL) *c = 0;
615 ipt_source(p, s);
617 if (remotemanage) {
618 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %d -j %s\n",
619 s, nvram_safe_get("lan_ipaddr"), web_lanport, chain_in_accept);
622 if (nvram_get_int("sshd_remote")) {
623 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %s -j %s\n",
624 s, nvram_safe_get("lan_ipaddr"), nvram_safe_get("sshd_port"), chain_in_accept);
627 if (!c) break;
628 p = c + 1;
629 } while (*p);
632 #ifdef TCONFIG_FTP // !!TB - FTP Server
633 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
634 strlcpy(t, nvram_safe_get("ftp_sip"), sizeof(t));
635 p = t;
636 do {
637 if ((c = strchr(p, ',')) != NULL) *c = 0;
638 ipt_source(p, s);
640 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
641 s, nvram_safe_get("ftp_port"), chain_in_accept);
643 if (!c) break;
644 p = c + 1;
645 } while (*p);
647 #endif
649 // IGMP query from WAN interface
650 if (nvram_match("multicast_pass", "1")) {
651 ipt_write("-A INPUT -p igmp -j ACCEPT\n");
654 // Routing protocol, RIP, accept
655 if (nvram_invmatch("dr_wan_rx", "0")) {
656 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
659 // if logging
660 if (*chain_in_drop == 'l') {
661 ipt_write( "-A INPUT -j %s\n", chain_in_drop);
664 // default policy: DROP
667 // clamp TCP MSS to PMTU of WAN interface
668 static void clampmss(void)
670 #if 1
671 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n");
672 #else
673 int rmtu = nvram_get_int("wan_run_mtu");
674 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu - 39);
675 if (rmtu < 576) {
676 ipt_write("--clamp-mss-to-pmtu\n");
678 else {
679 ipt_write("--set-mss %d\n", rmtu - 40);
681 #endif
684 static void filter_forward(void)
686 char dst[64];
687 char src[64];
688 char t[512];
689 char *p, *c;
691 ipt_write(
692 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
693 "-A FORWARD -m state --state INVALID -j DROP\n", // drop if INVALID state
694 lanface, lanface);
696 // clamp tcp mss to pmtu
697 clampmss();
699 if (wanup) {
700 ipt_restrictions();
701 ipt_layer7_inbound();
704 ipt_webmon();
706 ipt_write(
707 ":wanin - [0:0]\n"
708 ":wanout - [0:0]\n"
709 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
710 "-A FORWARD -i %s -j wanin\n" // generic from wan
711 "-A FORWARD -o %s -j wanout\n" // generic to wan
712 "-A FORWARD -i %s -j %s\n", // from lan
713 wanface, wanface, lanface, chain_out_accept);
715 if (*manface)
716 ipt_write(
717 "-A FORWARD -i %s -j wanin\n" // generic from wan
718 "-A FORWARD -o %s -j wanout\n", // generic to wan
719 manface, manface);
721 if (nvram_get_int("upnp_enable") & 3) {
722 ipt_write(
723 ":upnp - [0:0]\n"
724 "-A FORWARD -i %s -j upnp\n",
725 wanface);
726 if (*manface)
727 ipt_write(
728 "-A FORWARD -i %s -j upnp\n",
729 manface);
732 if (wanup) {
733 if (nvram_match("multicast_pass", "1")) {
734 ipt_write("-A wanin -p udp -m udp -d 224.0.0.0/4 -j %s\n", chain_in_accept);
736 ipt_triggered(IPT_TABLE_FILTER);
737 ipt_forward(IPT_TABLE_FILTER);
739 if (dmz_dst(dst)) {
740 strlcpy(t, nvram_safe_get("dmz_sip"), sizeof(t));
741 p = t;
742 do {
743 if ((c = strchr(p, ',')) != NULL) *c = 0;
744 ipt_source(p, src);
745 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface, src, dst, chain_in_accept);
746 if (!c) break;
747 p = c + 1;
748 } while (*p);
753 // default policy: DROP
756 static void filter_log(void)
758 int n;
759 char limit[128];
761 n = nvram_get_int("log_limit");
762 if ((n >= 1) && (n <= 9999)) {
763 sprintf(limit, "-m limit --limit %d/m", n);
765 else {
766 limit[0] = 0;
769 if ((*chain_in_drop == 'l') || (*chain_out_drop == 'l')) {
770 ip46t_write(
771 ":logdrop - [0:0]\n"
772 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
773 "-A logdrop -j DROP\n"
774 ":logreject - [0:0]\n"
775 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
776 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
777 limit, limit);
779 if ((*chain_in_accept == 'l') || (*chain_out_accept == 'l')) {
780 ip46t_write(
781 ":logaccept - [0:0]\n"
782 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
783 "-A logaccept -j ACCEPT\n",
784 limit);
788 #ifdef TCONFIG_IPV6
789 static void filter6_input(void)
791 char s[64];
792 char *en;
793 char *sec;
794 char *hit;
795 int n;
797 ip6t_write(
798 "-A INPUT -m rt --rt-type 0 -j %s\n"
799 /* "-A INPUT -m state --state INVALID -j %s\n" */
800 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
801 chain_in_drop/*, chain_in_drop*/);
803 #ifdef LINUX26
804 modprobe("xt_length");
805 ip6t_write("-A INPUT -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
807 strlcpy(s, nvram_safe_get("ne_shlimit"), sizeof(s));
808 if ((vstrsep(s, ",", &en, &hit, &sec) == 3) && ((n = atoi(en) & 3) != 0)) {
810 ? what if the user uses the start button in GUI ?
811 if (nvram_get_int("telnetd_eas"))
812 if (nvram_get_int("sshd_eas"))
814 modprobe("xt_recent");
816 ip6t_write(
817 "-N shlimit\n"
818 "-A shlimit -m recent --set --name shlimit\n"
819 "-A shlimit -m recent --update --hitcount %d --seconds %s --name shlimit -j %s\n",
820 atoi(hit) + 1, sec, chain_in_drop);
822 if (n & 1) {
823 ip6t_write("-A INPUT -i %s -p tcp --dport %s -m state --state NEW -j shlimit\n", lanface, nvram_safe_get("sshd_port"));
824 if (nvram_get_int("sshd_remote") && nvram_invmatch("sshd_rport", nvram_safe_get("sshd_port"))) {
825 ip6t_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_rport"));
828 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"));
830 #endif
832 ip6t_write(
833 "-A INPUT -i %s -j ACCEPT\n" // anything coming from LAN
834 "-A INPUT -i lo -j ACCEPT\n",
835 lanface );
837 // ICMPv6 rules
838 const int allowed_icmpv6[6] = { 1, 2, 3, 4, 128, 129 };
839 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
840 ip6t_write("-A INPUT -p icmpv6 --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
843 // Remote Managment
844 // TODO: create list for allowed remote ipv6 addresses? currently: unrestricted by src addr
845 if (remotemanage) {
846 ip6t_write("-A INPUT -p tcp -m tcp --dport %s -j %s\n",
847 nvram_safe_get("http_wanport"), chain_in_accept);
850 if (nvram_get_int("sshd_remote")) {
851 ip6t_write("-A INPUT -p tcp -m tcp --dport %s -j %s\n",
852 nvram_safe_get("sshd_rport"), chain_in_accept);
855 // TODO: FTP server
857 // if logging
858 if (*chain_in_drop == 'l') {
859 ip6t_write( "-A INPUT -j %s\n", chain_in_drop);
862 // default policy: DROP
865 static void filter6_forward(void)
867 int n;
869 ip6t_write(
870 "-A FORWARD -m rt --rt-type 0 -j DROP\n"
871 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
872 /*"-A FORWARD -m state --state INVALID -j DROP\n"*/, // drop if INVALID state
873 lanface, lanface);
875 #ifdef LINUX26
876 modprobe("xt_length");
877 ip6t_write("-A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT\n");
878 #endif
881 // clamp tcp mss to pmtu TODO?
882 // clampmss();
884 // TODO: support l7, restrictions, webmon on ipv6?
885 /* if (wanup) {
886 ipt_restrictions();
887 ipt_layer7_inbound();
890 ipt_webmon(); */
892 ip6t_write(
893 ":wanin - [0:0]\n"
894 ":wanout - [0:0]\n"
895 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
896 "-A FORWARD -i %s -j wanin\n" // generic from wan
897 "-A FORWARD -o %s -j wanout\n" // generic to wan
898 "-A FORWARD -i %s -j %s\n", // from lan
899 wan6face, wan6face, lanface, chain_out_accept);
901 // ICMPv6 rules
902 const int allowed_icmpv6[6] = { 1, 2, 3, 4, 128, 129 };
903 for (n = 0; n < sizeof(allowed_icmpv6)/sizeof(int); n++) {
904 ip6t_write("-A FORWARD -p icmpv6 --icmpv6-type %i -j %s\n", allowed_icmpv6[n], chain_in_accept);
907 if (wanup) {
908 //ipt_triggered(IPT_TABLE_FILTER);
909 ip6t_forward();
912 // default policy: DROP
915 #endif
917 static void filter_table(void)
919 ip46t_write(
920 "*filter\n"
921 ":INPUT DROP [0:0]\n"
922 ":OUTPUT ACCEPT [0:0]\n"
925 filter_log();
927 filter_input();
928 #ifdef TCONFIG_IPV6
929 filter6_input();
930 #endif
931 if ((gateway_mode) || (nvram_match("wk_mode_x", "1"))) {
932 ip46t_write(":FORWARD DROP [0:0]\n");
933 filter_forward();
934 #ifdef TCONFIG_IPV6
935 filter6_forward();
936 #endif
938 else {
939 ip46t_write(":FORWARD ACCEPT [0:0]\n");
940 clampmss();
942 ip46t_write("COMMIT\n");
946 // -----------------------------------------------------------------------------
948 int start_firewall(void)
950 DIR *dir;
951 struct dirent *dirent;
952 char s[256];
953 char *c;
954 int n;
955 int wanproto;
956 char *iptrestore_argv[] = { "iptables-restore", (char *)ipt_fname, NULL };
957 #ifdef TCONFIG_IPV6
958 char *ip6trestore_argv[] = { "ip6tables-restore", (char *)ip6t_fname, NULL };
959 #endif
961 simple_lock("firewall");
962 simple_lock("restrictions");
964 wanproto = get_wan_proto();
965 wanup = check_wanup();
969 block obviously spoofed IP addresses
971 rp_filter - BOOLEAN
972 1 - do source validation by reversed path, as specified in RFC1812
973 Recommended option for single homed hosts and stub network
974 routers. Could cause troubles for complicated (not loop free)
975 networks running a slow unreliable protocol (sort of RIP),
976 or using static routes.
977 0 - No source validation.
979 if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
980 while ((dirent = readdir(dir)) != NULL) {
981 sprintf(s, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent->d_name);
982 f_write_string(s, "1", 0, 0);
984 closedir(dir);
987 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
989 /* NAT performance tweaks
990 * These values can be overriden later if needed via firewall script
992 f_write_string("/proc/sys/net/core/netdev_max_backlog", "3072", 0, 0);
993 f_write_string("/proc/sys/net/core/somaxconn", "3072", 0, 0);
994 f_write_string("/proc/sys/net/ipv4/tcp_max_syn_backlog", "8192", 0, 0);
995 f_write_string("/proc/sys/net/ipv4/tcp_fin_timeout", "30", 0, 0);
996 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_intvl", "24", 0, 0);
997 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_probes", "3", 0, 0);
998 f_write_string("/proc/sys/net/ipv4/tcp_keepalive_time", "1800", 0, 0);
999 f_write_string("/proc/sys/net/ipv4/tcp_retries2", "5", 0, 0);
1000 f_write_string("/proc/sys/net/ipv4/tcp_syn_retries", "3", 0, 0);
1001 f_write_string("/proc/sys/net/ipv4/tcp_synack_retries", "3", 0, 0);
1002 f_write_string("/proc/sys/net/ipv4/tcp_tw_recycle", "1", 0, 0);
1003 f_write_string("/proc/sys/net/ipv4/tcp_tw_reuse", "1", 0, 0);
1005 /* DoS-related tweaks */
1006 f_write_string("/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses", "1", 0, 0);
1007 f_write_string("/proc/sys/net/ipv4/tcp_rfc1337", "1", 0, 0);
1008 f_write_string("/proc/sys/net/ipv4/ip_local_port_range", "1024 65535", 0, 0);
1010 #ifdef TCONFIG_EMF
1011 /* Force IGMPv2 due EMF limitations */
1012 if (nvram_get_int("emf_enable")) {
1013 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0);
1014 f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0);
1016 #endif
1018 n = nvram_get_int("log_in");
1019 chain_in_drop = (n & 1) ? "logdrop" : "DROP";
1020 chain_in_accept = (n & 2) ? "logaccept" : "ACCEPT";
1022 n = nvram_get_int("log_out");
1023 chain_out_drop = (n & 1) ? "logdrop" : "DROP";
1024 chain_out_reject = (n & 1) ? "logreject" : "REJECT --reject-with tcp-reset";
1025 chain_out_accept = (n & 2) ? "logaccept" : "ACCEPT";
1027 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
1029 strlcpy(lanface, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1031 manaddr[0] = '\0';
1032 manface[0] = '\0';
1034 if ((wanproto == WP_PPTP) || (wanproto == WP_L2TP) || (wanproto == WP_PPPOE)) {
1035 strcpy(wanface, "ppp+");
1037 else {
1038 strlcpy(wanface, nvram_safe_get("wan_ifname"), sizeof(wanface));
1041 strlcpy(wanaddr, get_wanip(), sizeof(wanaddr));
1042 c = nvram_safe_get("wan_ipaddr");
1043 if (*c && strcmp(c, wanaddr) != 0 && strcmp(c, "0.0.0.0") != 0) {
1044 strlcpy(manaddr, c, sizeof(manaddr));
1045 if ((wanproto == WP_PPTP) || (wanproto == WP_L2TP) || (wanproto == WP_PPPOE))
1046 strlcpy(manface, nvram_safe_get("wan_ifname"), sizeof(manface));
1049 #ifdef TCONFIG_IPV6
1050 if (nvram_match("ipv6_service", "native"))
1051 strlcpy(wan6face, wanface, sizeof(wan6face));
1052 else if (nvram_invmatch("ipv6_service", ""))
1053 strlcpy(wan6face, nvram_safe_get("ipv6_ifname"), sizeof(wan6face));
1054 #endif
1056 strlcpy(s, nvram_safe_get("lan_ipaddr"), sizeof(s));
1057 if ((c = strrchr(s, '.')) != NULL) *(c + 1) = 0;
1058 strlcpy(lan_cclass, s, sizeof(lan_cclass));
1060 gateway_mode = !nvram_match("wk_mode", "router");
1061 if (gateway_mode) {
1062 /* Remote management */
1063 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
1064 nvram_invmatch("http_wanport", "0")) remotemanage = 1;
1065 else remotemanage = 0;
1067 if (nvram_match("remote_mgt_https", "1")) {
1068 web_lanport = nvram_get_int("https_lanport");
1069 if (web_lanport <= 0) web_lanport = 443;
1071 else {
1072 web_lanport = nvram_get_int("http_lanport");
1073 if (web_lanport <= 0) web_lanport = 80;
1078 if ((ipt_file = fopen(ipt_fname, "w")) == NULL) {
1079 notice_set("iptables", "Unable to create iptables restore file");
1080 simple_unlock("firewall");
1081 return 0;
1084 #ifdef TCONFIG_IPV6
1085 if ((ip6t_file = fopen(ip6t_fname, "w")) == NULL) {
1086 notice_set("ip6tables", "Unable to create ip6tables restore file");
1087 simple_unlock("firewall");
1088 return 0;
1090 modprobe("nf_conntrack_ipv6");
1091 #endif
1093 mangle_table();
1094 nat_table();
1095 filter_table();
1097 fclose(ipt_file);
1098 ipt_file = NULL;
1100 #ifdef TCONFIG_IPV6
1101 fclose(ip6t_file);
1102 ip6t_file = NULL;
1103 #endif
1105 #ifdef DEBUG_IPTFILE
1106 if (debug_only) {
1107 simple_unlock("firewall");
1108 simple_unlock("restrictions");
1109 return 0;
1111 #endif
1113 save_webmon();
1115 if (nvram_get_int("upnp_enable") & 3) {
1116 f_write("/etc/upnp/save", NULL, 0, 0, 0);
1117 if (killall("miniupnpd", SIGUSR2) == 0) {
1118 f_wait_notexists("/etc/upnp/save", 5);
1122 notice_set("iptables", "");
1123 if (_eval(iptrestore_argv, ">/var/notice/iptables", 0, NULL) == 0) {
1124 led(LED_DIAG, 0);
1125 notice_set("iptables", "");
1127 else {
1128 sprintf(s, "%s.error", ipt_fname);
1129 rename(ipt_fname, s);
1130 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1131 led(LED_DIAG, 1);
1135 -P INPUT DROP
1136 -F INPUT
1137 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
1138 -A INPUT -i br0 -j ACCEPT
1140 -P FORWARD DROP
1141 -F FORWARD
1142 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
1143 -A FORWARD -i br0 -j ACCEPT
1148 #ifdef TCONFIG_IPV6
1149 if (nvram_invmatch("ipv6_service", "")) {
1150 notice_set("ip6tables", "");
1151 if (_eval(ip6trestore_argv, ">/var/notice/ip6tables", 0, NULL) == 0) {
1152 led(LED_DIAG, 0);
1153 notice_set("ip6tables", "");
1155 else {
1156 sprintf(s, "%s.error", ip6t_fname);
1157 rename(ip6t_fname, s);
1158 syslog(LOG_CRIT, "Error while loading rules. See %s file.", s);
1159 led(LED_DIAG, 1);
1162 #endif
1164 if (nvram_get_int("upnp_enable") & 3) {
1165 f_write("/etc/upnp/load", NULL, 0, 0, 0);
1166 killall("miniupnpd", SIGUSR2);
1169 simple_unlock("restrictions");
1170 sched_restrictions();
1171 enable_ip_forward();
1173 led(LED_DMZ, dmz_dst(NULL));
1175 #ifdef TCONFIG_IPV6
1176 modprobe_r("nf_conntrack_ipv6");
1177 #endif
1178 #ifdef LINUX26
1179 modprobe_r("xt_layer7");
1180 modprobe_r("xt_recent");
1181 modprobe_r("xt_HL");
1182 modprobe_r("xt_length");
1183 #else
1184 modprobe_r("ipt_layer7");
1185 modprobe_r("ipt_recent");
1186 modprobe_r("ipt_TTL");
1187 #endif
1188 modprobe_r("ipt_ipp2p");
1189 modprobe_r("ipt_web");
1190 modprobe_r("ipt_webmon");
1192 unlink("/var/webmon/domain");
1193 unlink("/var/webmon/search");
1195 #ifdef TCONFIG_OPENVPN
1196 run_vpn_firewall_scripts();
1197 #endif
1198 run_nvscript("script_fire", NULL, 1);
1200 simple_unlock("firewall");
1201 return 0;
1204 int stop_firewall(void)
1206 led(LED_DMZ, 0);
1207 return 0;
1210 #ifdef DEBUG_IPTFILE
1211 void create_test_iptfile(void)
1213 debug_only = 1;
1214 start_firewall();
1215 debug_only = 0;
1217 #endif