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
)
117 if ((*s
) && (strlen(s
) < 32))
119 if (sscanf(s
, "%[0-9.]-%[0-9.]", p
, p
) == 2)
120 sprintf(src
, "-m iprange --src-range %s", s
);
122 sprintf(src
, "-s %s", s
);
129 static void get_src(const char *nv, char *src)
133 if (((p = nvram_get(nv)) != NULL) && (*p) && (strlen(p) < 32)) {
134 sprintf(src, "-%s %s", strchr(p, '-') ? "m iprange --src-range" : "s", p);
142 void ipt_write(const char *format
, ...)
146 va_start(args
, format
);
147 vfprintf(ipt_file
, format
, args
);
151 // -----------------------------------------------------------------------------
154 int ipt_ipp2p(const char *v
, char *opt
)
163 strcpy(opt
, "-m ipp2p ");
164 if ((n
& 0xFFF) == 0xFFF) {
165 strcat(opt
, "--ipp2p");
169 if (n
& 0x0001) strcat(opt
, "--apple ");
170 if (n
& 0x0002) strcat(opt
, "--ares ");
171 if (n
& 0x0004) strcat(opt
, "--bit ");
172 if (n
& 0x0008) strcat(opt
, "--dc ");
173 if (n
& 0x0010) strcat(opt
, "--edk ");
174 if (n
& 0x0020) strcat(opt
, "--gnu ");
175 if (n
& 0x0040) strcat(opt
, "--kazaa ");
176 if (n
& 0x0080) strcat(opt
, "--mute ");
177 if (n
& 0x0100) strcat(opt
, "--soul ");
178 if (n
& 0x0200) strcat(opt
, "--waste ");
179 if (n
& 0x0400) strcat(opt
, "--winmx ");
180 if (n
& 0x0800) strcat(opt
, "--xdcc ");
183 modprobe("ipt_ipp2p");
188 // -----------------------------------------------------------------------------
193 // This L7 matches inbound traffic, caches the results, then the L7 outbound
194 // should read the cached result and set the appropriate marks -- zzz
195 void ipt_layer7_inbound(void)
200 if (!layer7_in
) return;
202 en
= nvram_match("nf_l7in", "1");
206 "-A FORWARD -i %s -j L7in\n",
212 if (en
) ipt_write("-A L7in %s -j RETURN\n", *p
);
220 int ipt_layer7(const char *v
, char *opt
)
226 if (*v
== 0) return 0;
227 if (strlen(v
) > 32) return -1;
229 path
= "/etc/l7-extra";
230 sprintf(s
, "%s/%s.pat", path
, v
);
232 path
= "/etc/l7-protocols";
233 sprintf(s
, "%s/%s.pat", path
, v
);
235 syslog(LOG_ERR
, "L7 %s was not found", v
);
240 sprintf(opt
, "-m layer7 --l7dir %s --l7proto %s", path
, v
);
242 if (nvram_match("nf_l7in", "1")) {
243 if (!layer7_in
) layer7_in
= calloc(51, sizeof(char *));
249 if (strcmp(*p
, opt
) == 0) return 1;
252 if (((p
- layer7_in
) / sizeof(char *)) < 50) *p
= strdup(opt
);
256 modprobe("ipt_layer7");
262 // -----------------------------------------------------------------------------
264 // -----------------------------------------------------------------------------
266 static void mangle_table(void)
273 ":PREROUTING ACCEPT [0:0]\n"
274 ":OUTPUT ACCEPT [0:0]\n");
279 ttl
= nvram_get_int("nf_ttl");
290 "-I PREROUTING -i %s -j TTL --ttl-%sc %d\n"
291 "-I POSTROUTING -o %s -j TTL --ttl-%sc %d\n",
297 ipt_write("COMMIT\n");
302 // -----------------------------------------------------------------------------
304 // -----------------------------------------------------------------------------
306 static void nat_table(void)
316 ":PREROUTING ACCEPT [0:0]\n"
317 ":POSTROUTING ACCEPT [0:0]\n"
318 ":OUTPUT ACCEPT [0:0]\n");
320 strlcpy(lanaddr
, nvram_safe_get("lan_ipaddr"), sizeof(lanaddr
));
321 strlcpy(lanmask
, nvram_safe_get("lan_netmask"), sizeof(lanmask
));
323 // Drop incoming packets which destination IP address is to our LAN side directly
324 ipt_write("-A PREROUTING -i %s -d %s/%s -j DROP\n",
326 lanaddr
, lanmask
); // note: ipt will correct lanaddr
329 if (nvram_match("dns_intcpt", "1")) {
330 ipt_write("-A PREROUTING -p udp -s %s/%s ! -d %s/%s --dport 53 -j DNAT --to-destination %s\n",
336 // ICMP packets are always redirected to INPUT chains
337 ipt_write("-A PREROUTING -p icmp -d %s -j DNAT --to-destination %s\n", wanaddr
, lanaddr
);
340 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
343 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
347 ipt_write("-A PREROUTING -p tcp -m tcp %s -d %s --dport %s -j DNAT --to-destination %s:%d\n",
349 wanaddr
, nvram_safe_get("http_wanport"),
350 lanaddr
, web_lanport
);
352 if (nvram_get_int("sshd_remote")) {
353 ipt_write("-A PREROUTING %s -p tcp -m tcp -d %s --dport %s -j DNAT --to-destination %s:%s\n",
355 wanaddr
, nvram_safe_get("sshd_rport"),
356 lanaddr
, nvram_safe_get("sshd_port"));
363 ipt_forward(IPT_TABLE_NAT
);
364 ipt_triggered(IPT_TABLE_NAT
);
367 if (nvram_get_int("upnp_enable") & 3) {
368 ipt_write(":upnp - [0:0]\n");
370 // ! for loopback (all) to work
371 ipt_write("-A PREROUTING -d %s -j upnp\n", wanaddr
);
374 ipt_write("-A PREROUTING -i %s -j upnp\n", wanface
);
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
);
392 if ((!wanup
) || (nvram_get_int("net_snat") != 1)) {
393 ipt_write("-A POSTROUTING -o %s -j MASQUERADE\n", wanface
);
396 ipt_write("-A POSTROUTING -o %s -j SNAT --to-source %s\n", wanface
, wanaddr
);
399 switch (nvram_get_int("nf_loopback")) {
400 case 1: // 1 = forwarded-only
401 case 2: // 2 = disable
403 default: // 0 = all (same as block_loopback=0)
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)
428 if ((nvram_get_int("nf_loopback") != 0) && (wanup
)) { // 0 = all
429 ipt_write("-A INPUT -i %s -d %s -j DROP\n", lanface
, wanaddr
);
433 "-A INPUT -m state --state INVALID -j %s\n"
434 "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n",
438 strlcpy(s
, nvram_safe_get("ne_shlimit"), sizeof(s
));
439 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && ((n
= atoi(en
) & 3) != 0)) {
441 ? what if the user uses the start button in GUI ?
442 if (nvram_get_int("telnetd_eas"))
443 if (nvram_get_int("sshd_eas"))
445 modprobe("ipt_recent");
449 "-A shlimit -m recent --set --name shlimit\n"
450 "-A shlimit -m recent --update --hitcount %s --seconds %s --name shlimit -j DROP\n",
453 if (n
& 1) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("sshd_port"));
454 if (n
& 2) ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j shlimit\n", nvram_safe_get("telnetd_port"));
458 strlcpy(s
, nvram_safe_get("ftp_limit"), sizeof(s
));
459 if ((vstrsep(s
, ",", &en
, &hit
, &sec
) == 3) && (atoi(en
)) && (nvram_get_int("ftp_enable") == 1)) {
460 modprobe("ipt_recent");
464 "-A ftplimit -m recent --set --name ftp\n"
465 "-A ftplimit -m recent --update --hitcount %s --seconds %s --name ftp -j DROP\n",
467 ipt_write("-A INPUT -p tcp --dport %s -m state --state NEW -j ftplimit\n", nvram_safe_get("ftp_port"));
472 "-A INPUT -i %s -j ACCEPT\n"
473 "-A INPUT -i lo -j ACCEPT\n",
476 // ICMP request from WAN interface
477 if (nvram_match("block_wan", "0")) {
478 ipt_write("-A INPUT -p icmp -j ACCEPT\n");
482 strlcpy(t
, nvram_safe_get("rmgt_sip"), sizeof(t
));
485 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
490 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %d -j %s\n",
491 s
, nvram_safe_get("lan_ipaddr"), web_lanport
, chain_in_accept
);
494 if (nvram_get_int("sshd_remote")) {
495 ipt_write("-A INPUT -p tcp %s -m tcp -d %s --dport %s -j %s\n",
496 s
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("sshd_port"), chain_in_accept
);
504 #ifdef TCONFIG_FTP // !!TB - FTP Server
505 if (nvram_match("ftp_enable", "1")) { // FTP WAN access enabled
506 strlcpy(t
, nvram_safe_get("ftp_sip"), sizeof(t
));
509 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
512 ipt_write("-A INPUT -p tcp %s -m tcp --dport %s -j %s\n",
513 s
, nvram_safe_get("ftp_port"), chain_in_accept
);
521 // IGMP query from WAN interface
522 if (nvram_match("multicast_pass", "1")) {
523 ipt_write("-A INPUT -p igmp -j ACCEPT\n");
526 // Routing protocol, RIP, accept
527 if (nvram_invmatch("dr_wan_rx", "0")) {
528 ipt_write("-A INPUT -p udp -m udp --dport 520 -j ACCEPT\n");
532 if (*chain_in_drop
== 'l') {
533 ipt_write( "-A INPUT -j %s\n", chain_in_drop
);
536 // default policy: DROP
539 // clamp TCP MSS to PMTU of WAN interface
540 static void clampmss(void)
542 int rmtu
= nvram_get_int("wan_run_mtu");
544 ipt_write("-A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss %d: -j TCPMSS ", rmtu
- 39);
546 ipt_write("--clamp-mss-to-pmtu\n");
549 ipt_write("--set-mss %d\n", rmtu
- 40);
553 static void filter_forward(void)
561 "-A FORWARD -i %s -o %s -j ACCEPT\n" // accept all lan to lan
562 "-A FORWARD -m state --state INVALID -j DROP\n", // drop if INVALID state
565 // clamp tcp mss to pmtu
570 ipt_layer7_inbound();
576 "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n" // already established or related (via helper)
577 "-A FORWARD -i %s -j wanin\n" // generic from wan
578 "-A FORWARD -o %s -j wanout\n" // generic to wan
579 "-A FORWARD -i %s -j %s\n", // from lan
580 wanface
, wanface
, lanface
, chain_out_accept
);
582 if (nvram_get_int("upnp_enable") & 3) {
585 "-A FORWARD -i %s -j upnp\n",
590 if (nvram_match("multicast_pass", "1")) {
591 ipt_write("-A wanin -p udp -m udp -d 224.0.0.0/4 -j %s\n", chain_in_accept
);
593 ipt_triggered(IPT_TABLE_FILTER
);
594 ipt_forward(IPT_TABLE_FILTER
);
597 strlcpy(t
, nvram_safe_get("dmz_sip"), sizeof(t
));
600 if ((c
= strchr(p
, ',')) != NULL
) *c
= 0;
602 ipt_write("-A FORWARD -o %s %s -d %s -j %s\n", lanface
, src
, dst
, chain_in_accept
);
610 // default policy: DROP
613 static void filter_table(void)
620 ":INPUT DROP [0:0]\n"
621 ":OUTPUT ACCEPT [0:0]\n"
624 n
= nvram_get_int("log_limit");
625 if ((n
>= 1) && (n
<= 9999)) {
626 sprintf(limit
, "-m limit --limit %d/m", n
);
632 if ((*chain_in_drop
== 'l') || (*chain_out_drop
== 'l')) {
635 "-A logdrop -m state --state NEW %s -j LOG --log-prefix \"DROP \" --log-tcp-options --log-ip-options\n"
636 "-A logdrop -j DROP\n"
637 ":logreject - [0:0]\n"
638 "-A logreject %s -j LOG --log-prefix \"REJECT \" --log-tcp-options --log-ip-options\n"
639 "-A logreject -p tcp -j REJECT --reject-with tcp-reset\n",
642 if ((*chain_in_accept
== 'l') || (*chain_out_accept
== 'l')) {
644 ":logaccept - [0:0]\n"
645 "-A logaccept -m state --state NEW %s -j LOG --log-prefix \"ACCEPT \" --log-tcp-options --log-ip-options\n"
646 "-A logaccept -j ACCEPT\n",
652 if ((gateway_mode
) || (nvram_match("wk_mode_x", "1"))) {
653 ipt_write(":FORWARD DROP [0:0]\n");
657 ipt_write(":FORWARD ACCEPT [0:0]\n");
660 ipt_write("COMMIT\n");
664 // -----------------------------------------------------------------------------
666 int start_firewall(void)
669 struct dirent
*dirent
;
675 simple_lock("firewall");
676 simple_lock("restrictions");
678 wanproto
= get_wan_proto();
679 wanup
= check_wanup();
683 block obviously spoofed IP addresses
686 1 - do source validation by reversed path, as specified in RFC1812
687 Recommended option for single homed hosts and stub network
688 routers. Could cause troubles for complicated (not loop free)
689 networks running a slow unreliable protocol (sort of RIP),
690 or using static routes.
691 0 - No source validation.
693 if ((dir
= opendir("/proc/sys/net/ipv4/conf")) != NULL
) {
694 while ((dirent
= readdir(dir
)) != NULL
) {
695 sprintf(s
, "/proc/sys/net/ipv4/conf/%s/rp_filter", dirent
->d_name
);
696 f_write_string(s
, "1", 0, 0);
701 f_write_string("/proc/sys/net/ipv4/tcp_syncookies", nvram_get_int("ne_syncookies") ? "1" : "0", 0, 0);
703 n
= nvram_get_int("log_in");
704 chain_in_drop
= (n
& 1) ? "logdrop" : "DROP";
705 chain_in_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
707 n
= nvram_get_int("log_out");
708 chain_out_drop
= (n
& 1) ? "logdrop" : "DROP";
709 chain_out_reject
= (n
& 1) ? "logreject" : "REJECT --reject-with tcp-reset";
710 chain_out_accept
= (n
& 2) ? "logaccept" : "ACCEPT";
712 // if (nvram_match("nf_drop_reset", "1")) chain_out_drop = chain_out_reject;
714 strlcpy(lanface
, nvram_safe_get("lan_ifname"), IFNAMSIZ
);
716 if ((wanproto
== WP_PPTP
) || (wanproto
== WP_L2TP
) || (wanproto
== WP_PPPOE
)) {
717 strcpy(wanface
, "ppp+");
720 strlcpy(wanface
, nvram_safe_get("wan_ifname"), sizeof(wanface
));
723 strlcpy(wanaddr
, get_wanip(), sizeof(wanaddr
));
725 strlcpy(s
, nvram_safe_get("lan_ipaddr"), sizeof(s
));
726 if ((c
= strrchr(s
, '.')) != NULL
) *(c
+ 1) = 0;
727 strlcpy(lan_cclass
, s
, sizeof(lan_cclass
));
729 gateway_mode
= !nvram_match("wk_mode", "router");
731 /* Remote management */
732 if (nvram_match("remote_management", "1") && nvram_invmatch("http_wanport", "") &&
733 nvram_invmatch("http_wanport", "0")) remotemanage
= 1;
734 else remotemanage
= 0;
736 if (nvram_match("remote_mgt_https", "1")) {
737 web_lanport
= nvram_get_int("https_lanport");
738 if (web_lanport
<= 0) web_lanport
= 443;
741 web_lanport
= nvram_get_int("http_lanport");
742 if (web_lanport
<= 0) web_lanport
= 80;
747 if ((ipt_file
= fopen(ipt_fname
, "w")) == NULL
) {
748 syslog(LOG_CRIT
, "Unable to create iptables restore file");
749 simple_unlock("firewall");
762 simple_unlock("firewall");
763 simple_unlock("restrictions");
768 if (nvram_get_int("upnp_enable") & 3) {
769 f_write("/etc/upnp/save", NULL
, 0, 0, 0);
770 if (killall("miniupnpd", SIGUSR2
) == 0) {
771 f_wait_notexists("/etc/upnp/save", 5);
775 if (eval("iptables-restore", (char *)ipt_fname
) == 0) {
779 sprintf(s
, "%s.error", ipt_fname
);
780 rename(ipt_fname
, s
);
781 syslog(LOG_CRIT
, "Error while loading rules. See %s file.", s
);
788 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
789 -A INPUT -i br0 -j ACCEPT
793 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
794 -A FORWARD -i br0 -j ACCEPT
799 if (nvram_get_int("upnp_enable") & 3) {
800 f_write("/etc/upnp/load", NULL
, 0, 0, 0);
801 killall("miniupnpd", SIGUSR2
);
804 simple_unlock("restrictions");
805 sched_restrictions();
808 led(LED_DMZ
, dmz_dst(NULL
));
810 modprobe_r("ipt_layer7");
811 modprobe_r("ipt_ipp2p");
812 modprobe_r("ipt_web");
813 modprobe_r("ipt_TTL");
815 run_nvscript("script_fire", NULL
, 1);
817 simple_unlock("firewall");
821 int stop_firewall(void)
828 void create_test_iptfile(void)