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 char wanface
[IFNAMSIZ
];
33 char lanface
[IFNAMSIZ
];
34 char lan_cclass
[sizeof("xxx.xxx.xxx.")];
35 char wanaddr
[sizeof("xxx.xxx.xxx.xxx")];
36 static int web_lanport
;
39 static int debug_only
= 0;
42 static int gateway_mode
;
43 static int remotemanage
;
46 const char *chain_in_drop
;
47 const char *chain_in_accept
;
48 const char *chain_out_drop
;
49 const char *chain_out_accept
;
50 const char *chain_out_reject
;
52 const char ipt_fname
[] = "/etc/iptables";
61 // -----------------------------------------------------------------------------
64 void enable_ip_forward(void)
68 0 - disabled (default)
71 Forward Packets between interfaces.
73 This variable is special, its change resets all configuration
74 parameters to their default state (RFC1122 for hosts, RFC1812
77 f_write_string("/proc/sys/net/ipv4/ip_forward", "1", 0, 0);
81 // -----------------------------------------------------------------------------
84 static int ip2cclass(char *ipaddr, char *new, int count)
88 if (sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]) != 4) return 0;
89 return snprintf(new, count, "%d.%d.%d.",ip[0],ip[1],ip[2]);
94 static int dmz_dst(char *s
)
100 if (nvram_get_int("dmz_enable") <= 0) return 0;
102 p
= nvram_safe_get("dmz_ipaddr");
103 if ((ia
.s_addr
= inet_addr(p
)) == (in_addr_t
)-1) {
104 if (((n
= atoi(p
)) <= 0) || (n
>= 255)) return 0;
105 if (s
) sprintf(s
, "%s%d", lan_cclass
, n
);
109 if (s
) strcpy(s
, inet_ntoa(ia
));
113 static void ipt_source(const char *s
, char *src
)
115 if ((*s
) && (strlen(s
) < 32)) sprintf(src
, "-%s %s", strchr(s
, '-') ? "m iprange --src-range" : "s", s
);
120 static void get_src(const char *nv, char *src)
124 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
125 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
133 void ipt_write(const char *format
, ...)
137 va_start(args
, format
);
138 vfprintf(ipt_file
, format
, args
);
142 // -----------------------------------------------------------------------------
145 int ipt_ipp2p(const char *v
, char *opt
)
154 strcpy(opt
, "-m ipp2p ");
155 if ((n
& 0xFFF) == 0xFFF) {
156 strcat(opt
, "--ipp2p");
160 if (n
& 0x0001) strcat(opt
, "--apple ");
161 if (n
& 0x0002) strcat(opt
, "--ares ");
162 if (n
& 0x0004) strcat(opt
, "--bit ");
163 if (n
& 0x0008) strcat(opt
, "--dc ");
164 if (n
& 0x0010) strcat(opt
, "--edk ");
165 if (n
& 0x0020) strcat(opt
, "--gnu ");
166 if (n
& 0x0040) strcat(opt
, "--kazaa ");
167 if (n
& 0x0080) strcat(opt
, "--mute ");
168 if (n
& 0x0100) strcat(opt
, "--soul ");
169 if (n
& 0x0200) strcat(opt
, "--waste ");
170 if (n
& 0x0400) strcat(opt
, "--winmx ");
171 if (n
& 0x0800) strcat(opt
, "--xdcc ");
174 modprobe("ipt_ipp2p");
179 // -----------------------------------------------------------------------------
184 // This L7 matches inbound traffic, caches the results, then the L7 outbound
185 // should read the cached result and set the appropriate marks -- zzz
186 void ipt_layer7_inbound(void)
191 if (!layer7_in
) return;
193 en
= nvram_match("nf_l7in", "1");
197 "-A FORWARD -i %s -j L7in\n",
203 if (en
) ipt_write("-A L7in %s -j RETURN\n", *p
);
211 int ipt_layer7(const char *v
, char *opt
)
217 if (*v
== 0) return 0;
218 if (strlen(v
) > 32) return -1;
220 path
= "/etc/l7-extra";
221 sprintf(s
, "%s/%s.pat", path
, v
);
223 path
= "/etc/l7-protocols";
224 sprintf(s
, "%s/%s.pat", path
, v
);
226 syslog(LOG_ERR
, "L7 %s was not found", v
);
231 sprintf(opt
, "-m layer7 --l7dir %s --l7proto %s", path
, v
);
233 if (nvram_match("nf_l7in", "1")) {
234 if (!layer7_in
) layer7_in
= calloc(51, sizeof(char *));
240 if (strcmp(*p
, opt
) == 0) return 1;
243 if (((p
- layer7_in
) / sizeof(char *)) < 50) *p
= strdup(opt
);
247 modprobe("ipt_layer7");
253 // -----------------------------------------------------------------------------
255 // -----------------------------------------------------------------------------
257 static void mangle_table(void)
264 ":PREROUTING ACCEPT [0:0]\n"
265 ":OUTPUT ACCEPT [0:0]\n");
270 ttl
= nvram_get_int("nf_ttl");
281 "-I PREROUTING -i %s -j TTL --ttl-%sc %d\n"
282 "-I POSTROUTING -o %s -j TTL --ttl-%sc %d\n",
288 ipt_write("COMMIT\n");
293 // -----------------------------------------------------------------------------
295 // -----------------------------------------------------------------------------
297 static void nat_table(void)
307 ":PREROUTING ACCEPT [0:0]\n"
308 ":POSTROUTING ACCEPT [0:0]\n"
309 ":OUTPUT ACCEPT [0:0]\n");
311 strlcpy(lanaddr
, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr
));
312 strlcpy(lanmask
, nvram_safe_get("lan_netmask"), sizeof(lanmask
));
314 // Drop incoming packets which destination IP address is to our LAN side directly
315 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
317 lanaddr
, lanmask
); // note: ipt will correct lanaddr
320 if (nvram_match("dns_intcpt", "1")) {
321 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
327 // ICMP packets are always redirected to INPUT chains
328 ipt_write("-A PREROUTING -p icmp -d %s -j DNAT --to-destination %s\n", wanaddr
, lanaddr
);
331 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
334 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
338 ipt_write("-A PREROUTING -p tcp -m tcp %s -d %s --dport %s -j DNAT --to-destination %s:%d\n",
340 wanaddr
, nvram_safe_get("http_wanport"),
341 lanaddr
, web_lanport
);
343 if (nvram_get_int("sshd_remote")) {
344 ipt_write("-A PREROUTING %s -p tcp -m tcp -d %s --dport %s -j DNAT --to-destination %s:%s\n",
346 wanaddr
, nvram_safe_get("sshd_rport"),
347 lanaddr
, nvram_safe_get("sshd_port"));
354 ipt_forward(IPT_TABLE_NAT
);
355 ipt_triggered(IPT_TABLE_NAT
);
359 if (nvram_get_int("upnp_enable") & 3) {
360 ipt_write(":upnp - [0:0]\n");
362 // ! for loopback (all) to work
363 ipt_write("-A PREROUTING -d %s -j upnp\n", wanaddr
);
366 ipt_write("-A PREROUTING -i %s -j upnp\n", wanface
);
370 if (nvram_get_int("upnp_enable")) {
373 "-A PREROUTING -i %s -j upnp\n",
380 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
383 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
385 ipt_write("-A PREROUTING %s -d %s -j DNAT --to-destination %s\n", src
, wanaddr
, dst
);
396 ipt_write("-A POSTROUTING -o %s -j MASQUERADE\n", wanface
);
398 switch (nvram_get_int("nf_loopback")) {
399 case 1: // 1 = forwarded-only
400 case 2: // 2 = disable
402 default: // 0 = all (same as block_loopback=0)
403 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j MASQUERADE\n",
410 ipt_write("COMMIT\n");
413 // -----------------------------------------------------------------------------
415 // -----------------------------------------------------------------------------
417 static void filter_input(void)
427 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
428 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanaddr
);
432 "-A INPUT -m state --state INVALID -j %s\n"
433 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
437 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
438 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
440 ? what if the user uses the start button in GUI ?
441 if (nvram_get_int("telnetd_eas"))
442 if (nvram_get_int("sshd_eas"))
444 modprobe("ipt_recent");
448 "-A shlimit -m recent --set --name shlimit\n"
449 "-A shlimit -m recent --update --hitcount %s --seconds %s --name shlimit -j DROP\n",
452 if (n
& 1) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
453 if (n
& 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
457 "-A INPUT -i %s -j ACCEPT\n"
458 "-A INPUT -i lo -j ACCEPT\n",
461 // ICMP request from WAN interface
462 if (nvram_match("block_wan", "0")) {
463 ipt_write("-A INPUT -p icmp -j ACCEPT\n");
467 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
470 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
475 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %d -j %s\n",
476 s
, nvram_safe_get("lan_ipaddr"), web_lanport
, chain_in_accept
);
479 if (nvram_get_int("sshd_remote")) {
480 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %s -j %s\n",
481 s
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("sshd_port"), chain_in_accept
);
489 // IGMP query from WAN interface
490 if (nvram_match("multicast_pass", "1")) {
491 ipt_write("-A INPUT -p igmp -j ACCEPT\n");
494 // Routing protocol, RIP, accept
495 if (nvram_invmatch("dr_wan_rx", "0")) {
496 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
500 if (*chain_in_drop
== 'l') {
501 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
504 // default policy: DROP
507 // clamp TCP MSS to PMTU of WAN interface
508 static void clampmss(void)
510 int rmtu
= nvram_get_int("wan_run_mtu");
512 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
514 ipt_write("--clamp-mss-to-pmtu\n");
517 ipt_write("--set-mss %d\n", rmtu
- 40);
521 static void filter_forward(void)
529 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
530 "-A FORWARD -m state --state INVALID -j DROP\n", // drop if INVALID state
533 // clamp tcp mss to pmtu
538 ipt_layer7_inbound();
544 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
545 "-A FORWARD -i %s -j wanin\n" // generic from wan
546 "-A FORWARD -o %s -j wanout\n" // generic to wan
547 "-A FORWARD -i %s -j %s\n", // from lan
548 wanface
, wanface
, lanface
, chain_out_accept
);
551 if (nvram_get_int("upnp_enable") & 3) {
554 "-A FORWARD -i %s -j upnp\n",
558 if (nvram_get_int("upnp_enable")) {
561 "-A FORWARD -i %s -j upnp\n",
567 if (nvram_match("multicast_pass", "1")) {
568 ipt_write("-A wanin -p udp -m udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
570 ipt_triggered(IPT_TABLE_FILTER
);
571 ipt_forward(IPT_TABLE_FILTER
);
574 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
577 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
579 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
587 // default policy: DROP
590 static void filter_table(void)
597 ":INPUT DROP [0:0]\n"
598 ":OUTPUT ACCEPT [0:0]\n"
601 n
= nvram_get_int("log_limit");
602 if ((n
>= 1) && (n
<= 9999)) {
603 sprintf(limit
, "-m limit --limit %d/m", n
);
609 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
612 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
613 "-A logdrop -j DROP\n"
614 ":logreject - [0:0]\n"
615 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
616 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
619 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
621 ":logaccept - [0:0]\n"
622 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
623 "-A logaccept -j ACCEPT\n",
629 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
630 ipt_write(":FORWARD DROP [0:0]\n");
634 ipt_write(":FORWARD ACCEPT [0:0]\n");
637 ipt_write("COMMIT\n");
641 // -----------------------------------------------------------------------------
643 int start_firewall(void)
646 struct dirent
*dirent
;
652 simple_lock("firewall");
653 simple_lock("restrictions");
655 wanproto
= get_wan_proto();
656 wanup
= check_wanup();
660 block obviously spoofed IP addresses
663 1 - do source validation by reversed path, as specified in RFC1812
664 Recommended option for single homed hosts and stub network
665 routers. Could cause troubles for complicated (not loop free)
666 networks running a slow unreliable protocol (sort of RIP),
667 or using static routes.
668 0 - No source validation.
670 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
671 while ((dirent
= readdir(dir
)) != NULL
) {
672 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
673 f_write_string(s
, "1", 0, 0);
678 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
680 n
= nvram_get_int("log_in");
681 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
682 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
684 n
= nvram_get_int("log_out");
685 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
686 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
687 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
689 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
691 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
693 if ((wanproto
== WP_PPTP
) || (wanproto
== WP_L2TP
) || (wanproto
== WP_PPPOE
)) {
694 strcpy(wanface
, "ppp+");
697 strlcpy(wanface
, nvram_safe_get("wan_ifname"), sizeof(wanface
));
700 strlcpy(wanaddr
, get_wanip(), sizeof(wanaddr
));
702 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
703 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
704 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
706 gateway_mode
= !nvram_match("wk_mode", "router");
708 /* Remote management */
709 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
710 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
711 else remotemanage
= 0;
713 if (nvram_match("remote_mgt_https", "1")) {
714 web_lanport
= nvram_get_int("https_lanport");
715 if (web_lanport
<= 0) web_lanport
= 443;
718 web_lanport
= nvram_get_int("http_lanport");
719 if (web_lanport
<= 0) web_lanport
= 80;
724 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
725 syslog(LOG_CRIT
, "Unable to create iptables restore file");
726 simple_unlock("firewall");
739 simple_unlock("firewall");
740 simple_unlock("restrictions");
746 if (nvram_get_int("upnp_enable") & 3) {
747 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
748 if (killall("miniupnpd", SIGUSR2
) == 0) {
749 f_wait_notexists("/etc/upnp/save", 5);
754 if (eval("iptables-restore", (char *)ipt_fname
) == 0) {
758 sprintf(s
, "%s.error", ipt_fname
);
759 rename(ipt_fname
, s
);
760 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
767 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
768 -A INPUT -i br0 -j ACCEPT
772 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
773 -A FORWARD -i br0 -j ACCEPT
779 if (nvram_get_int("upnp_enable") & 3) {
780 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
781 killall("miniupnpd", SIGUSR2
);
784 if (nvram_get_int("upnp_enable")) {
785 killall("upnp", SIGHUP
);
789 simple_unlock("restrictions");
790 sched_restrictions();
793 led(LED_DMZ
, dmz_dst(NULL
));
795 modprobe_r("ipt_layer7");
796 modprobe_r("ipt_ipp2p");
797 modprobe_r("ipt_web");
798 modprobe_r("ipt_TTL");
800 run_nvscript("script_fire", NULL
, 1);
802 simple_unlock("firewall");
806 int stop_firewall(void)
813 void create_test_iptfile(void)