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-2008 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_match("dmz_enable", "1")) 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 get_src(const char *nv
, char *src
)
117 if (((p
=nvram_get(nv
)) != NULL
) && (*p
) && (strlen(p
) < 32)) {
118 if (sscanf(p
,"%*d.%*d.%*d.%*d-%*d.%*d.%*d.%*d") == 8)
119 sprintf(src
, "-m iprange --src-range %s", p
);
121 sprintf(src
, "-s %s", p
);
128 void ipt_write(const char *format
, ...)
132 va_start(args
, format
);
133 vfprintf(ipt_file
, format
, args
);
138 // -----------------------------------------------------------------------------
141 int ipt_ipp2p(const char *v
, char *opt
)
150 strcpy(opt
, "-m ipp2p ");
151 if ((n
& 0xFFF) == 0xFFF) {
152 strcat(opt
, "--ipp2p");
156 if (n
& 0x0001) strcat(opt
, "--apple ");
157 if (n
& 0x0002) strcat(opt
, "--ares ");
158 if (n
& 0x0004) strcat(opt
, "--bit ");
159 if (n
& 0x0008) strcat(opt
, "--dc ");
160 if (n
& 0x0010) strcat(opt
, "--edk ");
161 if (n
& 0x0020) strcat(opt
, "--gnu ");
162 if (n
& 0x0040) strcat(opt
, "--kazaa ");
163 if (n
& 0x0080) strcat(opt
, "--mute ");
164 if (n
& 0x0100) strcat(opt
, "--soul ");
165 if (n
& 0x0200) strcat(opt
, "--waste ");
166 if (n
& 0x0400) strcat(opt
, "--winmx ");
167 if (n
& 0x0800) strcat(opt
, "--xdcc ");
170 modprobe("ipt_ipp2p");
175 // -----------------------------------------------------------------------------
180 // This L7 matches inbound traffic, caches the results, then the L7 outbound
181 // should read the cached result and set the appropriate marks -- zzz
182 void ipt_layer7_inbound(void)
187 if (!layer7_in
) return;
189 en
= nvram_match("nf_l7in", "1");
193 "-A FORWARD -i %s -j L7in\n",
199 if (en
) ipt_write("-A L7in %s -j RETURN\n", *p
);
207 int ipt_layer7(const char *v
, char *opt
)
213 if (*v
== 0) return 0;
214 if (strlen(v
) > 32) return -1;
216 path
= "/etc/l7-extra";
217 sprintf(s
, "%s/%s.pat", path
, v
);
219 path
= "/etc/l7-protocols";
220 sprintf(s
, "%s/%s.pat", path
, v
);
222 syslog(LOG_ERR
, "L7 %s was not found", v
);
227 sprintf(opt
, "-m layer7 --l7dir %s --l7proto %s", path
, v
);
229 if (nvram_match("nf_l7in", "1")) {
230 if (!layer7_in
) layer7_in
= calloc(51, sizeof(char *));
236 if (strcmp(*p
, opt
) == 0) return 1;
239 if (((p
- layer7_in
) / sizeof(char *)) < 50) *p
= strdup(opt
);
243 modprobe("ipt_layer7");
249 // -----------------------------------------------------------------------------
251 // -----------------------------------------------------------------------------
253 static void mangle_table(void)
260 ":PREROUTING ACCEPT [0:0]\n"
261 ":OUTPUT ACCEPT [0:0]\n");
266 ttl
= nvram_get_int("nf_ttl");
277 "-I PREROUTING -i %s -j TTL --ttl-%sc %d\n"
278 "-I POSTROUTING -o %s -j TTL --ttl-%sc %d\n",
284 ipt_write("COMMIT\n");
289 // -----------------------------------------------------------------------------
291 // -----------------------------------------------------------------------------
293 in_addr_t
_inet_addr(const char *cp
)
297 if (!inet_aton(cp
, &a
))
303 static void nat_table(void)
311 ":PREROUTING ACCEPT [0:0]\n"
312 ":POSTROUTING ACCEPT [0:0]\n"
313 ":OUTPUT ACCEPT [0:0]\n");
315 strlcpy(lanaddr
, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr
));
316 strlcpy(lanmask
, nvram_safe_get("lan_netmask"), sizeof(lanmask
));
318 // Drop incoming packets which destination IP address is to our LAN side directly
319 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
321 lanaddr
, lanmask
); // note: ipt will correct lanaddr
324 if (nvram_match("dns_intcpt", "1")) {
325 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
331 // ICMP packets are always redirected to INPUT chains
332 ipt_write("-A PREROUTING -p icmp -d %s -j DNAT --to-destination %s\n", wanaddr
, lanaddr
);
334 get_src("rmgt_sip", src
); // -s xxx or -m iprange --src-range xxx or ""
337 ipt_write("-A PREROUTING -p tcp -m tcp %s -d %s --dport %s -j DNAT --to-destination %s:%d\n",
339 wanaddr
, nvram_safe_get("http_wanport"),
340 lanaddr
, web_lanport
);
343 if (nvram_match("sshd_remote", "1")) {
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"));
350 ipt_forward(IPT_TABLE_NAT
);
351 ipt_triggered(IPT_TABLE_NAT
);
354 if (nvram_match("upnp_enable", "1") || nvram_match("upnp_nat_pmp_enable", "1")) { //!!TB - miniupnpd
357 "-A PREROUTING -i %s -j upnp\n",
363 get_src("dmz_sip", src
);
364 ipt_write("-A PREROUTING %s -d %s -j DNAT --to-destination %s\n", src
, wanaddr
, dst
);
370 /* Using SNAT instead of MASQUERADE can speed up routing since
371 * SNAT does not seek the external IP every time a chain is traversed.
372 * Recommended to use with kernel patch to drop SNAT'ed connections
373 * on wanface down or wanip change.
375 if (wanup
&& nvram_match("ne_snat", "1")) {
376 if (_inet_addr(wanaddr
))
377 ipt_write("-A POSTROUTING -o %s ! -s %s -j SNAT --to-source %s\n",
381 /* SNAT physical WAN port connection */
382 char *wanip
= nvram_safe_get("wan_ipaddr");
383 if (nvram_invmatch("wan_ifname", wanface
) && _inet_addr(wanip
))
384 ipt_write("-A POSTROUTING -o %s ! -s %s -j SNAT --to-source %s\n",
385 nvram_safe_get("wan_ifname"),
389 ipt_write("-A POSTROUTING -o %s -j MASQUERADE\n", wanface
);
392 switch (nvram_get_int("nf_loopback")) {
393 case 1: // 1 = forwarded-only
394 case 2: // 2 = disable
396 default: // 0 = all (same as block_loopback=0)
397 if (nvram_match("ne_snat", "1"))
398 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j SNAT --to-source %s\n",
404 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j MASQUERADE\n",
411 ipt_write("COMMIT\n");
414 // -----------------------------------------------------------------------------
416 // -----------------------------------------------------------------------------
418 static void filter_input(void)
422 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
423 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanaddr
);
426 // filter known SPI state
428 "-A INPUT -m state --state INVALID -j %s\n"
429 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
430 "-A INPUT -i %s -j ACCEPT\n"
431 "-A INPUT -i lo -j ACCEPT\n",
435 // ICMP request from WAN interface
436 if (nvram_match("block_wan", "0")) {
437 ipt_write("-A INPUT -p icmp -j ACCEPT\n");
440 get_src("rmgt_sip", src
); // -s xxx or -m iprange --src-range xxx or ""
443 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %d -j %s\n",
444 src
, nvram_safe_get("lan_ipaddr"), web_lanport
, chain_in_accept
);
447 if (nvram_match("sshd_remote", "1")) {
448 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %s -j %s\n",
449 src
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("sshd_port"), chain_in_accept
);
452 #ifdef TCONFIG_FTP // !!TB - FTP Server
453 if (nvram_match("ftp_enable", "1")) {
454 ipt_write("-A INPUT -p tcp -m tcp --dport %s -j %s\n",
455 nvram_safe_get("ftp_port"), chain_in_accept
);
459 // IGMP query from WAN interface
460 if (nvram_match("multicast_pass", "1")) {
461 ipt_write("-A INPUT -p igmp -j ACCEPT\n");
464 // Routing protocol, RIP, accept
465 if (nvram_invmatch("dr_wan_rx", "0")) {
466 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
470 if (*chain_in_drop
== 'l') {
471 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
474 // default policy: DROP
477 // clamp TCP MSS to PMTU of WAN interface
478 static void clampmss(void)
480 int rmtu
= nvram_get_int("wan_run_mtu");
482 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
484 ipt_write("--clamp-mss-to-pmtu\n");
487 ipt_write("--set-mss %d\n", rmtu
- 40);
491 static void filter_forward(void)
497 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
498 "-A FORWARD -m state --state INVALID -j DROP\n", // drop if INVALID state
501 // clamp tcp mss to pmtu
506 ipt_layer7_inbound();
512 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
513 "-A FORWARD -i %s -j wanin\n" // generic from wan
514 "-A FORWARD -o %s -j wanout\n" // generic to wan
515 "-A FORWARD -i %s -j %s\n", // from lan
516 wanface
, wanface
, lanface
, chain_out_accept
);
518 if (nvram_match("upnp_enable", "1") || nvram_match("upnp_nat_pmp_enable", "1")) { //!!TB - miniupnpd
521 "-A FORWARD -i %s -o ! %s -j upnp\n", //!!TB - miniupnpd
522 wanface
, wanface
); //!!TB - miniupnpd
526 if (nvram_match("multicast_pass", "1")) {
527 ipt_write("-A wanin -p udp -m udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
529 ipt_triggered(IPT_TABLE_FILTER
);
530 ipt_forward(IPT_TABLE_FILTER
);
533 get_src("dmz_sip", src
);
534 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
539 // default policy: DROP
542 static void filter_table(void)
549 ":INPUT DROP [0:0]\n"
550 ":OUTPUT ACCEPT [0:0]\n"
553 n
= nvram_get_int("log_limit");
554 if ((n
>= 1) && (n
<= 9999)) {
555 sprintf(limit
, "-m limit --limit %d/m", n
);
561 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
564 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
565 "-A logdrop -j DROP\n"
566 ":logreject - [0:0]\n"
567 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
568 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
571 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
573 ":logaccept - [0:0]\n"
574 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
575 "-A logaccept -j ACCEPT\n",
581 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
582 ipt_write(":FORWARD DROP [0:0]\n");
586 ipt_write(":FORWARD ACCEPT [0:0]\n");
589 ipt_write("COMMIT\n");
593 // -----------------------------------------------------------------------------
595 int start_firewall(void)
598 struct dirent
*dirent
;
604 simple_lock("firewall");
605 simple_lock("restrictions");
607 wanproto
= get_wan_proto();
608 wanup
= check_wanup();
612 block obviously spoofed IP addresses
615 1 - do source validation by reversed path, as specified in RFC1812
616 Recommended option for single homed hosts and stub network
617 routers. Could cause troubles for complicated (not loop free)
618 networks running a slow unreliable protocol (sort of RIP),
619 or using static routes.
620 0 - No source validation.
622 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
623 while ((dirent
= readdir(dir
)) != NULL
) {
624 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
625 f_write_string(s
, "1", 0, 0);
630 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
632 n
= nvram_get_int("log_in");
633 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
634 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
636 n
= nvram_get_int("log_out");
637 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
638 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
639 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
641 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
643 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
645 if ((wanproto
== WP_PPTP
) || (wanproto
== WP_L2TP
) || (wanproto
== WP_PPPOE
)) {
646 strcpy(wanface
, "ppp+");
649 strlcpy(wanface
, nvram_safe_get("wan_ifname"), sizeof(wanface
));
652 strlcpy(wanaddr
, get_wanip(), sizeof(wanaddr
));
654 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
655 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
656 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
658 gateway_mode
= !nvram_match("wk_mode", "router");
660 /* Remote management */
661 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
662 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
663 else remotemanage
= 0;
665 if (nvram_match("remote_mgt_https", "1")) {
666 web_lanport
= nvram_get_int("https_lanport");
667 if (web_lanport
<= 0) web_lanport
= 443;
670 web_lanport
= nvram_get_int("http_lanport");
671 if (web_lanport
<= 0) web_lanport
= 80;
676 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
677 syslog(LOG_CRIT
, "Unable to create iptables restore file");
678 simple_unlock("firewall");
691 simple_unlock("firewall");
696 if (eval("iptables-restore", (char *)ipt_fname
) == 0) {
697 // if (!nvram_match("debug_keepfiles", "1")) unlink(ipt_fname);
701 sprintf(s
, "%s.error", ipt_fname
);
702 rename(ipt_fname
, s
);
703 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
710 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
711 -A INPUT -i br0 -j ACCEPT
715 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
716 -A FORWARD -i br0 -j ACCEPT
722 if (nvram_match("upnp_enable", "1") || nvram_match("upnp_nat_pmp_enable", "1")) {
723 // flush all upnp rules
724 eval("iptables", "-t", "nat", "-F", "upnp");
725 eval("iptables", "-t", "filter", "-F", "upnp");
727 // system("/tmp/upnptest post");
729 // killall("upnp", SIGHUP);
733 simple_unlock("restrictions");
734 sched_restrictions();
737 led(LED_DMZ
, dmz_dst(NULL
));
739 modprobe_r("ipt_layer7");
740 modprobe_r("ipt_ipp2p");
741 modprobe_r("ipt_web");
742 modprobe_r("ipt_TTL");
744 #ifdef TCONFIG_OPENVPN
745 run_vpn_firewall_scripts();
747 run_nvscript("script_fire", NULL
, 1);
749 simple_unlock("firewall");
753 int stop_firewall(void)
760 void create_test_iptfile(void)