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
);
358 if (nvram_get_int("upnp_enable") & 3) {
359 ipt_write(":upnp - [0:0]\n");
361 // ! for loopback (all) to work
362 ipt_write("-A PREROUTING -d %s -j upnp\n", wanaddr
);
365 ipt_write("-A PREROUTING -i %s -j upnp\n", wanface
);
371 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
374 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
376 ipt_write("-A PREROUTING %s -d %s -j DNAT --to-destination %s\n", src
, wanaddr
, dst
);
383 if ((!wanup
) || (nvram_get_int("net_snat") != 1)) {
384 ipt_write("-A POSTROUTING -o %s -j MASQUERADE\n", wanface
);
387 ipt_write("-A POSTROUTING -o %s -j SNAT --to-source %s\n", wanface
, wanaddr
);
390 switch (nvram_get_int("nf_loopback")) {
391 case 1: // 1 = forwarded-only
392 case 2: // 2 = disable
394 default: // 0 = all (same as block_loopback=0)
395 ipt_write("-A POSTROUTING -o %s -s %s/%s -d %s/%s -j MASQUERADE\n",
402 ipt_write("COMMIT\n");
405 // -----------------------------------------------------------------------------
407 // -----------------------------------------------------------------------------
409 static void filter_input(void)
419 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
420 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanaddr
);
424 "-A INPUT -m state --state INVALID -j %s\n"
425 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
429 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
430 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
432 ? what if the user uses the start button in GUI ?
433 if (nvram_get_int("telnetd_eas"))
434 if (nvram_get_int("sshd_eas"))
436 modprobe("ipt_recent");
440 "-A shlimit -m recent --set --name shlimit\n"
441 "-A shlimit -m recent --update --hitcount %s --seconds %s --name shlimit -j DROP\n",
444 if (n
& 1) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
445 if (n
& 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
449 "-A INPUT -i %s -j ACCEPT\n"
450 "-A INPUT -i lo -j ACCEPT\n",
453 // ICMP request from WAN interface
454 if (nvram_match("block_wan", "0")) {
455 ipt_write("-A INPUT -p icmp -j ACCEPT\n");
459 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
462 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
467 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %d -j %s\n",
468 s
, nvram_safe_get("lan_ipaddr"), web_lanport
, chain_in_accept
);
471 if (nvram_get_int("sshd_remote")) {
472 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %s -j %s\n",
473 s
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("sshd_port"), chain_in_accept
);
481 // IGMP query from WAN interface
482 if (nvram_match("multicast_pass", "1")) {
483 ipt_write("-A INPUT -p igmp -j ACCEPT\n");
486 // Routing protocol, RIP, accept
487 if (nvram_invmatch("dr_wan_rx", "0")) {
488 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
492 if (*chain_in_drop
== 'l') {
493 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
496 // default policy: DROP
499 // clamp TCP MSS to PMTU of WAN interface
500 static void clampmss(void)
502 int rmtu
= nvram_get_int("wan_run_mtu");
504 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
506 ipt_write("--clamp-mss-to-pmtu\n");
509 ipt_write("--set-mss %d\n", rmtu
- 40);
513 static void filter_forward(void)
521 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
522 "-A FORWARD -m state --state INVALID -j DROP\n", // drop if INVALID state
525 // clamp tcp mss to pmtu
530 ipt_layer7_inbound();
536 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
537 "-A FORWARD -i %s -j wanin\n" // generic from wan
538 "-A FORWARD -o %s -j wanout\n" // generic to wan
539 "-A FORWARD -i %s -j %s\n", // from lan
540 wanface
, wanface
, lanface
, chain_out_accept
);
542 if (nvram_get_int("upnp_enable") & 3) {
545 "-A FORWARD -i %s -j upnp\n",
550 if (nvram_match("multicast_pass", "1")) {
551 ipt_write("-A wanin -p udp -m udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
553 ipt_triggered(IPT_TABLE_FILTER
);
554 ipt_forward(IPT_TABLE_FILTER
);
557 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
560 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
562 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
570 // default policy: DROP
573 static void filter_table(void)
580 ":INPUT DROP [0:0]\n"
581 ":OUTPUT ACCEPT [0:0]\n"
584 n
= nvram_get_int("log_limit");
585 if ((n
>= 1) && (n
<= 9999)) {
586 sprintf(limit
, "-m limit --limit %d/m", n
);
592 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
595 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
596 "-A logdrop -j DROP\n"
597 ":logreject - [0:0]\n"
598 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
599 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
602 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
604 ":logaccept - [0:0]\n"
605 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
606 "-A logaccept -j ACCEPT\n",
612 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
613 ipt_write(":FORWARD DROP [0:0]\n");
617 ipt_write(":FORWARD ACCEPT [0:0]\n");
620 ipt_write("COMMIT\n");
624 // -----------------------------------------------------------------------------
626 int start_firewall(void)
629 struct dirent
*dirent
;
635 simple_lock("firewall");
636 simple_lock("restrictions");
638 wanproto
= get_wan_proto();
639 wanup
= check_wanup();
643 block obviously spoofed IP addresses
646 1 - do source validation by reversed path, as specified in RFC1812
647 Recommended option for single homed hosts and stub network
648 routers. Could cause troubles for complicated (not loop free)
649 networks running a slow unreliable protocol (sort of RIP),
650 or using static routes.
651 0 - No source validation.
653 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
654 while ((dirent
= readdir(dir
)) != NULL
) {
655 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
656 f_write_string(s
, "1", 0, 0);
661 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
663 n
= nvram_get_int("log_in");
664 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
665 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
667 n
= nvram_get_int("log_out");
668 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
669 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
670 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
672 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
674 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
676 if ((wanproto
== WP_PPTP
) || (wanproto
== WP_L2TP
) || (wanproto
== WP_PPPOE
)) {
677 strcpy(wanface
, "ppp+");
680 strlcpy(wanface
, nvram_safe_get("wan_ifname"), sizeof(wanface
));
683 strlcpy(wanaddr
, get_wanip(), sizeof(wanaddr
));
685 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
686 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
687 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
689 gateway_mode
= !nvram_match("wk_mode", "router");
691 /* Remote management */
692 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
693 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
694 else remotemanage
= 0;
696 if (nvram_match("remote_mgt_https", "1")) {
697 web_lanport
= nvram_get_int("https_lanport");
698 if (web_lanport
<= 0) web_lanport
= 443;
701 web_lanport
= nvram_get_int("http_lanport");
702 if (web_lanport
<= 0) web_lanport
= 80;
707 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
708 syslog(LOG_CRIT
, "Unable to create iptables restore file");
709 simple_unlock("firewall");
722 simple_unlock("firewall");
723 simple_unlock("restrictions");
728 if (nvram_get_int("upnp_enable") & 3) {
729 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
730 if (killall("miniupnpd", SIGUSR2
) == 0) {
731 f_wait_notexists("/etc/upnp/save", 5);
735 if (eval("iptables-restore", (char *)ipt_fname
) == 0) {
739 sprintf(s
, "%s.error", ipt_fname
);
740 rename(ipt_fname
, s
);
741 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
748 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
749 -A INPUT -i br0 -j ACCEPT
753 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
754 -A FORWARD -i br0 -j ACCEPT
759 if (nvram_get_int("upnp_enable") & 3) {
760 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
761 killall("miniupnpd", SIGUSR2
);
764 simple_unlock("restrictions");
765 sched_restrictions();
768 led(LED_DMZ
, dmz_dst(NULL
));
770 modprobe_r("ipt_layer7");
771 modprobe_r("ipt_ipp2p");
772 modprobe_r("ipt_web");
773 modprobe_r("ipt_TTL");
775 run_nvscript("script_fire", NULL
, 1);
777 simple_unlock("firewall");
781 int stop_firewall(void)
788 void create_test_iptfile(void)