/* * Copyright 2004, ASUSTek Inc. * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND ASUS GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id: firewall_ex.c,v 1.9 2008/12/04 10:52:32 james26_jang Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define foreach_x(x) for(i=0; i3) { strcpy(g_buf, proto+4); } else strcpy(g_buf,""); } return (g_buf_alloc(g_buf)); } char *portrange_ex_conv(char *port_name, int idx) { char *port, *strptr; char itemname_arr[32]; sprintf(itemname_arr,"%s%d", port_name, idx); port=nvram_get(itemname_arr); strcpy(g_buf, ""); if(!strncmp(port, ">", 1)) { sprintf(g_buf, "%d-65535", atoi(port+1) + 1); } else if(!strncmp(port, "=", 1)) { sprintf(g_buf, "%d-%d", atoi(port+1), atoi(port+1)); } else if(!strncmp(port, "<", 1)) { sprintf(g_buf, "1-%d", atoi(port+1) - 1); } else if ((strptr=strchr(port, ':')) != NULL) { strcpy(itemname_arr, port); strptr = strchr(itemname_arr, ':'); sprintf(g_buf, "%d-%d", atoi(itemname_arr), atoi(strptr+1)); } else if(*port) { sprintf(g_buf, "%d-%d", atoi(port), atoi(port)); } else { g_buf[0] = 0; } return(g_buf_alloc(g_buf)); } char *portrange_ex2_conv(char *port_name, int idx, int *start, int *end) { char *port, *strptr; char itemname_arr[32]; sprintf(itemname_arr,"%s%d", port_name, idx); port=nvram_get(itemname_arr); strcpy(g_buf, ""); if(!strncmp(port, ">", 1)) { sprintf(g_buf, "%d-65535", atoi(port+1) + 1); *start=atoi(port+1); *end=65535; } else if(!strncmp(port, "=", 1)) { sprintf(g_buf, "%d-%d", atoi(port+1), atoi(port+1)); *start=*end=atoi(port+1); } else if(!strncmp(port, "<", 1)) { sprintf(g_buf, "1-%d", atoi(port+1) - 1); *start=1; *end=atoi(port+1); } else if( (strptr=strchr(port, ':')) != NULL) { strcpy(itemname_arr, port); strptr = strchr(itemname_arr, ':'); sprintf(g_buf, "%d-%d", atoi(itemname_arr), atoi(strptr+1)); *start=atoi(itemname_arr); *end=atoi(strptr+1); } else if(*port) { sprintf(g_buf, "%d-%d", atoi(port), atoi(port)); *start=atoi(port); *end=atoi(port); } else { g_buf[0] = 0; *start=0; *end=0; } return(g_buf_alloc(g_buf)); } char *portrange_conv(char *port_name, int idx) { char itemname_arr[32]; sprintf(itemname_arr,"%s%d", port_name, idx); strcpy(g_buf, nvram_safe_get(itemname_arr)); return(g_buf_alloc(g_buf)); } char *iprange_conv(char *ip_name, int idx) { char *ip; char itemname_arr[32]; char startip[16], endip[16]; int i, j, k; sprintf(itemname_arr,"%s%d", ip_name, idx); ip=nvram_safe_get(itemname_arr); strcpy(g_buf, ""); // scan all ip string i=j=k=0; while(*(ip+i)) { if (*(ip+i)=='*') { startip[j++] = '1'; endip[k++] = '2'; endip[k++] = '5'; endip[k++] = '4'; // 255 is for broadcast } else { startip[j++] = *(ip+i); endip[k++] = *(ip+i); } i++; } startip[j++] = 0; endip[k++] = 0; if (strcmp(startip, endip)==0) sprintf(g_buf, "%s", startip); else sprintf(g_buf, "%s-%s", startip, endip); return(g_buf_alloc(g_buf)); } char *iprange_ex_conv(char *ip_name, int idx) { char *ip; char itemname_arr[32]; char startip[16], endip[16]; int i, j, k; int mask; sprintf(itemname_arr,"%s%d", ip_name, idx); ip=nvram_safe_get(itemname_arr); strcpy(g_buf, ""); // scan all ip string i=j=k=0; mask=32; while(*(ip+i)) { if (*(ip+i)=='*') { startip[j++] = '0'; endip[k++] = '0'; // 255 is for broadcast mask-=8; } else { startip[j++] = *(ip+i); endip[k++] = *(ip+i); } i++; } startip[j++] = 0; endip[k++] = 0; if (mask==32) sprintf(g_buf, "%s", startip); else if(mask==0) strcpy(g_buf, ""); else sprintf(g_buf, "%s/%d", startip, mask); return(g_buf_alloc(g_buf)); } char *ip_conv(char *ip_name, int idx) { char itemname_arr[32]; sprintf(itemname_arr,"%s%d", ip_name, idx); sprintf(g_buf, "%s", nvram_safe_get(itemname_arr)); return(g_buf_alloc(g_buf)); } char *general_conv(char *ip_name, int idx) { char itemname_arr[32]; sprintf(itemname_arr,"%s%d", ip_name, idx); sprintf(g_buf, "%s", nvram_safe_get(itemname_arr)); return(g_buf_alloc(g_buf)); } char *filter_conv(char *proto, char *flag, char *srcip, char *srcport, char *dstip, char *dstport) { char newstr[64]; //printf("filter : %s,%s,%s,%s,%s,%s\n", proto, flag, srcip, srcport, dstip, dstport); strcpy(g_buf, ""); if (strcmp(proto, "")!=0) { sprintf(newstr, " -p %s", proto); strcat(g_buf, newstr); } if (strcmp(flag, "")!=0) { sprintf(newstr, " --tcp-flags %s RST", flag); strcat(g_buf, newstr); } if (strcmp(srcip, "")!=0) { if (strchr(srcip , '-')) sprintf(newstr, " --src-range %s", srcip); else sprintf(newstr, " -s %s", srcip); strcat(g_buf, newstr); } if (strcmp(srcport, "")!=0) { sprintf(newstr, " --sport %s", srcport); strcat(g_buf, newstr); } if (strcmp(dstip, "")!=0) { if (strchr(dstip, '-')) sprintf(newstr, " --dst-range %s", dstip); else sprintf(newstr, " -d %s", dstip); strcat(g_buf, newstr); } if (strcmp(dstport, "")!=0) { sprintf(newstr, " --dport %s", dstport); strcat(g_buf, newstr); } return(g_buf_alloc(g_buf)); //printf("str: %s\n", g_buf); } void timematch_conv(char *mstr, char *nv_date, char *nv_time) { char *datestr[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; char timestart[6], timestop[6]; char *time, *date; int i, head; date = nvram_safe_get(nv_date); time = nvram_safe_get(nv_time); if (strlen(date)!=7||strlen(time)!=8) goto no_match; if (strncmp(date, "1111111", 7)==0 && strncmp(time, "00002359", 8)==0) goto no_match; i=0; strncpy(timestart, time, 2); i+=2; timestart[i++] = ':'; strncpy(timestart+i, time+2, 2); i+=2; timestart[i]=0; i=0; strncpy(timestop, time+4, 2); i+=2; timestop[i++] = ':'; strncpy(timestop+i, time+6, 2); i+=2; timestop[i]=0; sprintf(mstr, "-m time --timestart %s:00 --timestop %s:00 --days", timestart, timestop); head=1; for(i=0;i<7;i++) { if (*(date+i)=='1') { if (head) { sprintf(mstr, "%s %s", mstr, datestr[i]); head=0; } else { sprintf(mstr, "%s,%s", mstr, datestr[i]); } } } return; no_match: mstr[0] = 0; return; } void p(int step) { dprintf("P: %d %s\n", step, g_buf); } void ip2class(char *lan_ip, char *netmask, char *buf) { unsigned int val, ip; struct in_addr in; int i=0; val = (unsigned int)inet_addr(netmask); ip = (unsigned int)inet_addr(lan_ip); in.s_addr = ip & val; for (val = ntohl(val); val; i++) val <<= 1; sprintf(buf, "%s/%d", inet_ntoa(in), i); dprintf(buf); } void convert_routes(void) { int i; char *ip, *netmask, *gateway, *matric, *interface; char wroutes[1024], lroutes[1024], mroutes[1024]; wroutes[0] = 0; lroutes[0] = 0; mroutes[0] = 0; g_buf_init(); if (nvram_match("sr_enable_x", "1")) foreach_x("sr_num_x") { ip = general_conv("sr_ipaddr_x", i); netmask = general_conv("sr_netmask_x", i); gateway = general_conv("sr_gateway_x", i); matric = general_conv("sr_matric_x", i); interface = general_conv("sr_if_x", i); dprintf("%x %s %s %s %s %s\n", i, ip, netmask, gateway, matric, interface); if (!strcmp(interface, "WAN")) { sprintf(wroutes, "%s %s:%s:%s:%d", wroutes, ip, netmask, gateway, atoi(matric)+1); } else if (!strcmp(interface, "LAN")) { sprintf(lroutes, "%s %s:%s:%s:%d", lroutes, ip, netmask, gateway, atoi(matric)+1); } else if (!strcmp(interface, "MAN")) { sprintf(mroutes, "%s %s:%s:%s:%d", mroutes, ip, netmask, gateway, atoi(matric)+1); } } //printf("route: %s %s\n", lroutes, wroutes); nvram_set("lan_route", lroutes); nvram_set("wan0_route", wroutes); nvram_set("wan_route", mroutes); } void write_static_leases(char *file) { FILE *fp; char *ip, *mac; int i; fp=fopen(file, "w"); if (fp==NULL) return; g_buf_init(); foreach_x("dhcp_staticnum_x") { ip = general_conv("dhcp_staticip_x", i); mac = general_conv("dhcp_staticmac_x", i); fprintf(fp, "%s,%s\r\n", ip, mac); } fclose(fp); } #ifndef NOIPTABLES void write_upnp_forward(FILE *fp, char *wan_if, char *wan_ip, char *lan_if, char *lan_ip, char *lan_class, char *logaccept, char *logdrop) { char name[] = "forward_portXXXXXXXXXX", value[512]; char *wan_port0, *wan_port1, *lan_ipaddr, *lan_port0, *lan_port1, *proto; char *enable, *desc; int i; /* Set wan_port0-wan_port1>lan_ipaddr:lan_port0-lan_port1,proto,enable,desc */ for(i=0 ; i<15 ; i++) { snprintf(name, sizeof(name), "forward_port%d", i); strncpy(value, nvram_safe_get(name), sizeof(value)); /* Check for LAN IP address specification */ lan_ipaddr = value; wan_port0 = strsep(&lan_ipaddr, ">"); if (!lan_ipaddr) continue; /* Check for LAN destination port specification */ lan_port0 = lan_ipaddr; lan_ipaddr = strsep(&lan_port0, ":"); if (!lan_port0) continue; /* Check for protocol specification */ proto = lan_port0; lan_port0 = strsep(&proto, ":,"); if (!proto) continue; /* Check for enable specification */ enable = proto; proto = strsep(&enable, ":,"); if (!enable) continue; /* Check for description specification (optional) */ desc = enable; enable = strsep(&desc, ":,"); /* Check for WAN destination port range (optional) */ wan_port1 = wan_port0; wan_port0 = strsep(&wan_port1, "-"); if (!wan_port1) wan_port1 = wan_port0; /* Check for LAN destination port range (optional) */ lan_port1 = lan_port0; lan_port0 = strsep(&lan_port1, "-"); if (!lan_port1) lan_port1 = lan_port0; /* skip if it's disabled */ if( strcmp(enable, "off") == 0 ) continue; /* -A PREROUTING -p tcp -m tcp --dport 823 -j DNAT --to-destination 192.168.1.88:23 */ if( !strcmp(proto,"tcp") || !strcmp(proto,"both") ) { fprintf(fp, "-A VSERVER -p tcp -m tcp --dport %s " "-j DNAT --to-destination %s:%s\n" , wan_port0, lan_ipaddr, lan_port0); } if( !strcmp(proto,"udp") || !strcmp(proto,"both") ){ fprintf(fp, "-A VSERVER -p udp -m udp --dport %s " "-j DNAT --to-destination %s:%s\n" , wan_port0, lan_ipaddr, lan_port0); } } } char *ipoffset(char *ip, int offset, char *tmp) { unsigned int ip1, ip2, ip3, ip4; sscanf(ip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); sprintf(tmp, "%d.%d.%d.%d", ip1, ip2, ip3, ip4+offset); dprintf("ip : %s\n", tmp); return(tmp); } #ifdef WEB_REDIRECT void redirect_setting() { FILE *nat_fp = fopen("/tmp/nat_rules", "r"); FILE *redirect_fp = fopen("/tmp/redirect_rules", "w+"); char tmp_buf[1024]; #ifndef NETGEAR_WAY char http_rule[256]; #endif char dns_rule[256]; char *lan_ipaddr_t = nvram_safe_get("lan_ipaddr_t"); char *lan_netmask_t = nvram_safe_get("lan_netmask_t"); if(redirect_fp == NULL){ fprintf(stderr, "*** Can't make the file of the redirect rules! ***\n"); return; } if(nat_fp != NULL){ memset(tmp_buf, 0, sizeof(tmp_buf)); while((fgets(tmp_buf, sizeof(tmp_buf), nat_fp)) != NULL && strncmp(tmp_buf, "COMMIT", 6) != 0){ fprintf(redirect_fp, "%s", tmp_buf); memset(tmp_buf, 0, sizeof(tmp_buf)); } fclose(nat_fp); } else{ // 2009.12 James. { FILE *del_redirect_fp = fopen("/tmp/del_redirect_rules", "w+"); if(del_redirect_fp != NULL){ fprintf(del_redirect_fp, "*nat\n"); fprintf(del_redirect_fp, "-F\n"); fprintf(del_redirect_fp, "COMMIT\n"); fclose(del_redirect_fp); } // 2009.12 James. } fprintf(redirect_fp, "*nat\n"); fprintf(redirect_fp, ":PREROUTING ACCEPT [0:0]\n"); } #ifndef NETGEAR_WAY memset(http_rule, 0, sizeof(http_rule)); #endif memset(dns_rule, 0, sizeof(dns_rule)); #ifndef NETGEAR_WAY sprintf(http_rule, "-A PREROUTING -i ! lo -d ! %s/%s -p tcp --dport 80 -j DNAT --to-destination %s:18017\n", lan_ipaddr_t, lan_netmask_t, lan_ipaddr_t); #endif sprintf(dns_rule, "-A PREROUTING -i ! lo -p udp --dport 53 -j DNAT --to-destination %s:18018\n", lan_ipaddr_t); #ifndef NETGEAR_WAY fprintf(redirect_fp, "%s", http_rule); #endif fprintf(redirect_fp, "%s", dns_rule); fprintf(redirect_fp, "COMMIT\n"); fclose(redirect_fp); } #endif void nat_setting(char *wan_if, char *wan_ip, char *lan_if, char *lan_ip, char *logaccept, char *logdrop) { FILE *fp; char lan_class[32]; int i; int wan_port; char dstips[32], dstports[12]; if ((fp=fopen("/tmp/nat_rules", "w"))==NULL) return; fprintf(fp, "*nat\n" ":PREROUTING ACCEPT [0:0]\n" ":POSTROUTING ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ":VSERVER - [0:0]\n"); //Log //if(nvram_match("misc_natlog_x", "1")) // fprintf(fp, "-A PREROUTING -i %s -j LOG --log-prefix ALERT --log-level 4\n", wan_if); /* VSERVER chain */ if (inet_addr_(wan_ip)) fprintf(fp, "-A PREROUTING -d %s -j VSERVER\n", wan_ip); if (nvram_invmatch("wan0_ifname", wan_if) && inet_addr_(nvram_safe_get("wanx_ipaddr"))) fprintf(fp, "-A PREROUTING -d %s -j VSERVER\n", nvram_get("wanx_ipaddr")); if (nvram_match("misc_http_x", "1")) { wan_port=8080; if (nvram_invmatch("misc_httpport_x", "")) wan_port=atoi(nvram_safe_get("misc_httpport_x")); fprintf(fp, "-A VSERVER -p tcp -m tcp --dport %d -j DNAT --to-destination %s:%s\n", wan_port, lan_ip, nvram_safe_get("http_lanport")); } if (nvram_match("apps_dl_share", "1")) { fprintf(fp, "-A VSERVER -p tcp -m tcp --dport %s:%s -j DNAT --to %s\n", nvram_safe_get("apps_dl_share_port_from"), nvram_safe_get("apps_dl_share_port_to"), lan_ip); fprintf(fp, "-A VSERVER -p udp -m udp --dport %s:%s -j DNAT --to %s\n", nvram_safe_get("apps_dl_share_port_from"), nvram_safe_get("apps_dl_share_port_to"), lan_ip); } if (nvram_match("wan_nat_x", "1") && nvram_invmatch("upnp_enable", "0")) { // upnp port forward write_upnp_forward(fp, wan_if, wan_ip, lan_if, lan_ip, lan_class, logaccept, logdrop); } // Port forwarding or Virtual Server if (nvram_match("wan_nat_x", "1") && nvram_match("vts_enable_x", "1")) { g_buf_init(); foreach_x("vts_num_x") { char *proto; char *protono; char *port; char *lport; char *dstip; proto = proto_conv("vts_proto_x", i); protono = portrange_conv("vts_protono_x", i); port = portrange_conv("vts_port_x", i); lport = portrange_conv("vts_lport_x", i); dstip = ip_conv("vts_ipaddr_x", i); if (lport!=NULL && strlen(lport)!=0) { sprintf(dstips, "%s:%s", dstip, lport); sprintf(dstports, "%s", lport); } else { sprintf(dstips, "%s:%s", dstip, port); sprintf(dstports, "%s", port); } if (strcmp(proto, "tcp")==0 || strcmp(proto, "both")==0) { if (lport!=NULL && strlen(lport)!=0) { fprintf(fp, "-A VSERVER -p tcp -m tcp --dport %s -j DNAT --to-destination %s\n", port, dstips); } else { fprintf(fp, "-A VSERVER -p tcp -m tcp --dport %s -j DNAT --to %s\n", port, dstip); } } if (strcmp(proto, "udp")==0 || strcmp(proto, "both")==0) { if (lport!=NULL && strlen(lport)!=0) { fprintf(fp, "-A VSERVER -p udp -m udp --dport %s -j DNAT --to-destination %s\n", port, dstips); } else { fprintf(fp, "-A VSERVER -p udp -m udp --dport %s -j DNAT --to %s\n", port, dstip); } } if (strcmp(proto, "other")==0) { fprintf(fp, "-A VSERVER -p %s -j DNAT --to %s\n", protono, dstip); } } } if (nvram_match("wan_nat_x", "1") && nvram_invmatch("sp_battle_ips", "0") && inet_addr_(wan_ip)) { #define BASEPORT 6112 #define BASEPORT_NEW 10000 ip2class(lan_ip, nvram_safe_get("lan_netmask"), lan_class); /* run starcraft patch anyway */ fprintf(fp, "-A PREROUTING -p udp -d %s --sport %d -j NETMAP --to %s\n", wan_ip, BASEPORT, lan_class); fprintf(fp, "-A POSTROUTING -p udp -s %s --dport %d -j NETMAP --to %s\n", lan_class, BASEPORT, wan_ip); } // Exposed station if (nvram_match("wan_nat_x", "1") && nvram_invmatch("dmz_ip", "")) { fprintf(fp, "-A VSERVER -j DNAT --to %s\n", nvram_safe_get("dmz_ip")); } if (nvram_match("wan_nat_x", "1")) { if(inet_addr_(wan_ip)) fprintf(fp, "-A POSTROUTING -o %s ! -s %s -j MASQUERADE\n", wan_if, wan_ip); /* masquerade physical WAN port connection */ if (nvram_invmatch("wan0_ifname", wan_if) && inet_addr_(nvram_safe_get("wanx_ipaddr"))) fprintf(fp, "-A POSTROUTING -o %s ! -s %s -j MASQUERADE\n", nvram_get("wan0_ifname"), nvram_get("wanx_ipaddr")); // masquerade lan to lan ip2class(lan_ip, nvram_safe_get("lan_netmask"), lan_class); fprintf(fp, "-A POSTROUTING -o %s -s %s -d %s -j MASQUERADE\n", lan_if, lan_class, lan_class); } fprintf(fp, "COMMIT\n"); fclose(fp); eval("iptables-restore", "/tmp/nat_rules"); #ifdef WEB_REDIRECT // for rebuild the rule of wanduck //kill_pidfile_s("/var/run/wanduck.pid", SIGUSR1); redirect_setting(); nvram_set("wan_ready", "1"); #endif } /* Rules for LW Filter and MAC Filter * MAC ACCEPT * ACCEPT -> MACS * -> LW Disabled * MACS ACCEPT * -> LW Default Accept: * MACS DROP in rules * MACS ACCEPT Default * -> LW Default Drop: * MACS ACCEPT in rules * MACS DROP Default * DROP -> FORWARD DROP * * MAC DROP * DROP -> FORWARD DROP * ACCEPT -> FORWARD ACCEPT */ int filter_setting(char *wan_if, char *wan_ip, char *lan_if, char *lan_ip, char *logaccept, char *logdrop) { FILE *fp; char *proto, *flag, *srcip, *srcport, *dstip, *dstport; char *setting, line[256]; char macaccept[32], chain[3]; char *ftype, *dtype, *fftype; int num; int i; //int wan_port; #ifdef WEBSTRFILTER/* Cherry Cho added in 2007/12/12. */ #if ADDRULE char nvname[36], *filterstr; #endif #endif if ((fp=fopen("/tmp/filter_rules", "w"))==NULL) return -1; fprintf(fp, "*filter\n:INPUT ACCEPT [0:0]\n:FORWARD ACCEPT [0:0]\n:OUTPUT ACCEPT [0:0]\n:MACS - [0:0]\n:logaccept - [0:0]\n:logdrop - [0:0]\n"); strcpy(macaccept, ""); // FILTER from LAN to WAN Source MAC if(nvram_invmatch("macfilter_enable_x", "0")) { // LAN/WAN filter g_buf_init(); if (nvram_match("macfilter_enable_x", "2")) { dtype = logaccept; ftype = logdrop; fftype = logdrop; } else { dtype = logdrop; ftype = logaccept; strcpy(macaccept, "MACS"); fftype = macaccept; } num = atoi(nvram_safe_get("macfilter_num_x")); for(i = 0; i < num; ++i) { fprintf(fp, "-A INPUT -i %s -m mac --mac-source %s -j %s\n", lan_if, mac_conv("macfilter_list_x", i, line), ftype); fprintf(fp, "-A FORWARD -i %s -m mac --mac-source %s -j %s\n", lan_if, mac_conv("macfilter_list_x", i, line), fftype); #ifdef GUEST_ACCOUNT if(nvram_match("wl_guest_enable", "1")) { fprintf(fp, "-A INPUT -i %s -m mac --mac-source %s -j %s\n", "wl0.1", mac_conv("macfilter_list_x", i, line), ftype); fprintf(fp, "-A FORWARD -i %s -m mac --mac-source %s -j %s\n", "wl0.1", mac_conv("macfilter_list_x", i, line), fftype); } #endif } } if (nvram_invmatch("fw_enable_x", "1")) { if (nvram_match("macfilter_enable_x", "1")) { /* Filter known SPI state */ fprintf(fp, "-A INPUT -i %s -m state --state NEW -j %s\n" ,lan_if, logdrop); #ifdef GUEST_ACCOUNT if(nvram_match("wl_guest_enable", "1")) { fprintf(fp, "-I INPUT -i %s -m state --state NEW -j %s\n" , "wl0.1", logdrop); } #endif } } else { if (nvram_match("macfilter_enable_x", "1")) { /* Filter known SPI state */ fprintf(fp, "-A INPUT -m state --state INVALID -j %s\n" "-A INPUT -m state --state RELATED,ESTABLISHED -j %s\n" "-A INPUT -i lo -m state --state NEW -j %s\n" "-A INPUT -i %s -m state --state NEW -j %s\n" ,logdrop, logaccept, "ACCEPT", lan_if, logdrop); #ifdef GUEST_ACCOUNT if(nvram_match("wl_guest_enable", "1")) { fprintf(fp, "-I INPUT -i %s -m state --state NEW -j %s\n" , "wl0.1", logdrop); } #endif } else { /* Filter known SPI state */ fprintf(fp, "-A INPUT -m state --state INVALID -j %s\n" "-A INPUT -m state --state RELATED,ESTABLISHED -j %s\n" "-A INPUT -i lo -m state --state NEW -j %s\n" "-A INPUT -i %s -m state --state NEW -j %s\n" ,logdrop, logaccept, "ACCEPT", lan_if, "ACCEPT"); #ifdef GUEST_ACCOUNT if(nvram_match("wl_guest_enable", "1")) { fprintf(fp, "-I INPUT -i %s -m state --state NEW -j %s\n" , "wl0.1", "ACCEPT"); } #endif } /* Pass multicast */ if (nvram_match("mr_enable_x", "1")) { fprintf(fp, "-A INPUT -p 2 -d 224.0.0.0/4 -j %s\n", logaccept); fprintf(fp, "-A INPUT -p udp -d 224.0.0.0/4 -j %s\n", logaccept); } /* enable incoming packets from broken dhcp servers, which are sending replies * from addresses other than used for query, this could lead to lower level * of security, but it does not work otherwise (conntrack does not work) :-( */ if (nvram_match("wan0_proto", "dhcp") #ifdef BIGPOND || nvram_match("wan0_proto", "bigpond") #endif || nvram_match("wan_ipaddr", "0.0.0.0")) { fprintf(fp, "-A INPUT -p udp --sport 67 --dport 68 -j %s\n", logaccept); } #ifdef GUEST_ACCOUNT if(nvram_match("wl_guest_enable", "1")) { fprintf(fp, "-I INPUT -i %s -p tcp -m tcp --dport 80 -j %s\n", "wl0.1", logdrop); //fprintf(fp, "-I INPUT -i %s -p icmp -j %s\n", "wl0.1", logdrop); fprintf(fp, "-I FORWARD -i %s -o br0 -j %s\n", "wl0.1", logdrop); fprintf(fp, "-I FORWARD -i br0 -o %s -j %s\n", "wl0.1", logdrop); #ifdef USB_SUPPORT fprintf(fp, "-I INPUT -i %s -p tcp -m tcp --dport %s -j %s\n", "wl0.1", nvram_safe_get("usb_webhttpport_x"), logdrop); fprintf(fp, "-I INPUT -i %s -p tcp -m tcp --dport %s -j %s\n", "wl0.1", nvram_safe_get("usb_ftpport_x"), logdrop); fprintf(fp, "-I INPUT -i %s -p tcp -m tcp --dport %s -j %s\n", "wl0.1", nvram_safe_get("usb_webactivex_x"), logdrop); fprintf(fp, "-I INPUT -i %s -p tcp -m tcp --dport %s -j %s\n", "wl0.1", "515", logdrop); fprintf(fp, "-I INPUT -i %s -p tcp -m tcp --dport %s -j %s\n", "wl0.1", "9100", logdrop); fprintf(fp, "-I INPUT -i %s -p tcp -m tcp --dport %s -j %s\n", "wl0.1", "3838", logdrop); #endif } #endif // Firewall between WAN and Local if (nvram_match("misc_http_x", "1")) { fprintf(fp, "-A INPUT -p tcp -m tcp -d %s --dport 80 -j %s\n", nvram_safe_get("lan_ipaddr"), logaccept); } if (nvram_match("usb_webenable_x", "2")) { fprintf(fp, "-A INPUT -p tcp -m tcp --dport %s -j %s\n", nvram_safe_get("usb_webhttpport_x"), logaccept); fprintf(fp, "-A INPUT -p tcp -m tcp --dport %s -j %s\n", nvram_safe_get("usb_webactivex_x"), logaccept); } if (nvram_invmatch("usb_ftpenable_x", "0")) { fprintf(fp, "-A INPUT -p tcp -m tcp --dport %s -j %s\n", nvram_safe_get("usb_ftpport_x"), logaccept); } if (nvram_invmatch("misc_ping_x", "0")) { fprintf(fp, "-A INPUT -p icmp -j %s\n", logaccept); } if (nvram_invmatch("misc_lpr_x", "0")) { fprintf(fp, "-A INPUT -p tcp -m tcp --dport %d -j %s\n", 515, logaccept); fprintf(fp, "-A INPUT -p tcp -m tcp --dport %d -j %s\n", 9100, logaccept); fprintf(fp, "-A INPUT -p tcp -m tcp --dport %d -j %s\n", 3838, logaccept); } fprintf(fp, "-A INPUT -j %s\n", logdrop); } /* Pass multicast */ if (nvram_match("mr_enable_x", "1")) { fprintf(fp, "-A FORWARD -p udp -d 224.0.0.0/4 -j ACCEPT\n"); if (strlen(macaccept)>0) fprintf(fp, "-A MACS -p udp -d 224.0.0.0/4 -j ACCEPT\n"); } /* Clamp TCP MSS to PMTU of WAN interface before accepting RELATED packets */ if (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "pptp") || nvram_match("wan_proto", "l2tp") #ifdef CDMA // HSDPA || strcmp(nvram_safe_get("hsdpa_product"), "") != 0 #endif ) { fprintf(fp, "-A FORWARD -p tcp --syn -j TCPMSS --clamp-mss-to-pmtu\n"); if (strlen(macaccept)>0) fprintf(fp, "-A MACS -p tcp --syn -j TCPMSS --clamp-mss-to-pmtu\n"); } fprintf(fp, "-A FORWARD -m state --state ESTABLISHED,RELATED -j %s\n", logaccept); if (strlen(macaccept)>0) fprintf(fp, "-A MACS -m state --state ESTABLISHED,RELATED -j %s\n", logaccept); /* Filter out invalid WAN->WAN connections */ fprintf(fp, "-A FORWARD -o %s ! -i %s -j %s\n", wan_if, lan_if, logdrop); // 2008.03 James. { //if (nvram_invmatch("wan0_ifname", wan_if)) if(nvram_invmatch("wan0_ifname", wan_if) && inet_addr_(nvram_safe_get("wanx_ipaddr"))) // 2008.03 James. } fprintf(fp, "-A FORWARD -o %s ! -i %s -j %s\n", nvram_get("wan0_ifname"), lan_if, logdrop); /* Drop the wrong state, INVALID, packets */ fprintf(fp, "-A FORWARD -m state --state INVALID -j %s\n", logdrop); if (strlen(macaccept)>0) fprintf(fp, "-A MACS -m state --state INVALID -j %s\n", logdrop); /* Accept the redirect, might be seen as INVALID, packets */ fprintf(fp, "-A FORWARD -i %s -o %s -j %s\n", lan_if, lan_if, logaccept); if (strlen(macaccept)>0) { fprintf(fp, "-A MACS -i %s -o %s -j %s\n", lan_if, lan_if, logaccept); #ifdef GUEST_ACCOUNT if(nvram_match("wl_guest_enable", "1")) { fprintf(fp, "-A MACS -i wl0.1 -o wl0.1 -j %s\n", logaccept); } #endif } if (nvram_match("fw_enable_x", "1") && !nvram_match("fw_dos_x", "0")) { // DoS attacks // sync-flood protection fprintf(fp, "-A FORWARD -i %s -p tcp --syn -m limit --limit 1/s -j %s\n", wan_if, logaccept); // furtive port scanner fprintf(fp, "-A FORWARD -i %s -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j %s\n", wan_if, logaccept); // ping of death fprintf(fp, "-A FORWARD -i %s -p icmp --icmp-type echo-request -m limit --limit 1/s -j %s\n", wan_if, logaccept); } // FILTER from LAN to WAN // Rules for MAC Filter and LAN to WAN Filter // Drop rules always before Accept if(nvram_match("macfilter_enable_x", "1")) strcpy(chain, "MACS"); else strcpy(chain, "FORWARD"); if(nvram_match("fw_lw_enable_x", "1")) { char lanwan_timematch[128]; char ptr[32], *icmplist; char *ftype, *dtype; timematch_conv(lanwan_timematch, "filter_lw_date_x", "filter_lw_time_x"); if (nvram_match("filter_lw_default_x", "DROP")) { dtype = logdrop; ftype = logaccept; } else { dtype = logaccept; ftype = logdrop; } // LAN/WAN filter g_buf_init(); foreach_x("filter_lw_num_x") { proto = protoflag_conv("filter_lw_proto_x", i, 0); flag = protoflag_conv("filter_lw_proto_x", i, 1); srcip = iprange_ex_conv("filter_lw_srcip_x", i); srcport = portrange_conv("filter_lw_srcport_x", i); dstip = iprange_ex_conv("filter_lw_dstip_x", i); dstport = portrange_conv("filter_lw_dstport_x", i); setting=filter_conv(proto, flag, srcip, srcport, dstip, dstport); fprintf(fp, "-A %s %s -i %s -o %s%s -j %s\n", chain, lanwan_timematch, lan_if, wan_if, setting, ftype); } // ICMP foreach(ptr, nvram_safe_get("filter_lw_icmp_x"), icmplist) { fprintf(fp, "-A %s %s -i %s -o %s -p icmp --icmp-type %s -j %s\n", chain, lanwan_timematch, lan_if, wan_if, ptr, ftype); } // Default fprintf(fp, "-A %s -i %s -o %s -j %s\n", chain, lan_if, wan_if, dtype); } else if (nvram_match("macfilter_enable_x", "1")) { fprintf(fp, "-A FORWARD -i %s -o %s -j %s\n", lan_if, wan_if, logdrop); fprintf(fp, "-A MACS -i %s -o %s -j %s\n", lan_if, wan_if, logaccept); } // Filter from WAN to LAN if(nvram_match("fw_wl_enable_x", "1")) { char wanlan_timematch[128]; char ptr[32], *icmplist; char *dtype, *ftype; timematch_conv(wanlan_timematch, "filter_wl_date_x", "filter_wl_time_x"); g_buf_init(); if (nvram_match("filter_wl_default_x", "DROP")) { dtype = logdrop; ftype = logaccept; } else { dtype = logaccept; ftype = logdrop; } foreach_x("filter_wl_num_x") { proto = protoflag_conv("filter_wl_proto_x", i, 0); flag = protoflag_conv("filter_wl_proto_x", i, 1); srcip = iprange_ex_conv("filter_wl_srcip_x", i); srcport = portrange_conv("filter_wl_srcport_x", i); dstip = iprange_ex_conv("filter_wl_dstip_x", i); dstport = portrange_conv("filter_wl_dstport_x", i); setting=filter_conv(proto, flag, srcip, srcport, dstip, dstport); fprintf(fp, "-A FORWARD %s -i %s -o %s%s -j %s\n", wanlan_timematch, wan_if, lan_if, setting, ftype); } // ICMP foreach(ptr, nvram_safe_get("filter_wl_icmp_x"), icmplist) { fprintf(fp, "-A FORWARD %s -i %s -o %s -p icmp --icmp-type %s -j %s\n", wanlan_timematch, wan_if, lan_if, ptr, ftype); } // thanks for Oleg // Default // fprintf(fp, "-A FORWARD -i %s -o %s -j %s\n", wan_if, lan_if, dtype); } /* Enable Virtual Servers */ fprintf(fp, "-A FORWARD -m conntrack --ctstate DNAT -j %s\n", logaccept); if (nvram_match("wan_nat_x", "1") && nvram_invmatch("sp_battle_ips", "0")) { fprintf(fp, "-A FORWARD -p udp --dport %d -j %s\n", BASEPORT, logaccept); } if(nvram_match("fw_wl_enable_x", "1")) // Thanks for Oleg { // Default fprintf(fp, "-A FORWARD -i %s -o %s -j %s\n", wan_if, lan_if, nvram_match("filter_wl_default_x", "DROP") ? logdrop : logaccept); } /* logaccept chain */ fprintf(fp, "-A logaccept -m state --state NEW -j LOG --log-prefix \"ACCEPT \" " "--log-tcp-sequence --log-tcp-options --log-ip-options\n" "-A logaccept -j ACCEPT\n"); /* logdrop chain */ fprintf(fp,"-A logdrop -m state --state NEW -j LOG --log-prefix \"DROP\" " "--log-tcp-sequence --log-tcp-options --log-ip-options\n" "-A logdrop -j DROP\n"); #ifdef WEBSTRFILTER/* Cherry Cho added in 2007/12/12. */ #if ADDRULE #ifdef USEOLDNV if (nvram_match("url_enable_x", "1")){ for(i=0; imatch.ipproto = IPPROTO_TCP; else if (!strncasecmp(out_proto, "udp", 3)) app->match.ipproto = IPPROTO_UDP; else continue; /* Parse outbound port range */ app->match.dst.ports[0] = htons(out_start); app->match.dst.ports[1] = htons(out_end); /* Parse related protocol */ if (!strncasecmp(in_proto, "tcp", 3)) app->proto = IPPROTO_TCP; else if (!strncasecmp(in_proto, "udp", 3)) app->proto = IPPROTO_UDP; else continue; /* Parse related destination port range */ app->dport[0] = htons(in_start); app->dport[1] = htons(in_end); /* Parse mapped destination port range */ app->to[0] = htons(in_start); app->to[1] = htons(in_end); /* Parse description */ if (desc) strncpy(app->desc, desc, sizeof(app->desc)); /* Set interface name (match packets entering LAN interface) */ strncpy(app->match.in.name, nvram_safe_get("lan_ifname"), IFNAMSIZ); /* Set LAN source port range (match packets from any source port) */ app->match.src.ports[1] = htons(0xffff); /* Set target (application specific port forward) */ app->target = NETCONF_APP; if (valid_autofw_port(app)) { netconf_add_fw((netconf_fw_t *)app); } } return 0; } int start_firewall_ex(char *wan_if, char *wan_ip, char *lan_if, char *lan_ip) { DIR *dir; struct dirent *file; FILE *fp; char name[NAME_MAX]; char logaccept[32], logdrop[32]; char *mcast_ifname = nvram_get("wan0_ifname"); /* mcast needs rp filter to be turned off only for non default iface */ if (!nvram_match("mr_enable_x", "1") || strcmp(wan_if, mcast_ifname) == 0) mcast_ifname = NULL; /* Block obviously spoofed IP addresses */ if (!(dir = opendir("/proc/sys/net/ipv4/conf"))) perror("/proc/sys/net/ipv4/conf"); while (dir && (file = readdir(dir))) { if (strncmp(file->d_name, ".", NAME_MAX) != 0 && strncmp(file->d_name, "..", NAME_MAX) != 0) { sprintf(name, "/proc/sys/net/ipv4/conf/%s/rp_filter", file->d_name); if (!(fp = fopen(name, "r+"))) { perror(name); break; } fputc(mcast_ifname && strncmp(file->d_name, mcast_ifname, NAME_MAX) == 0 ? '0' : '1', fp); fclose(fp); } } closedir(dir); /* Determine the log type */ if(nvram_match("fw_log_x", "accept") || nvram_match("fw_log_x", "both")) strcpy(logaccept, "logaccept"); else strcpy(logaccept, "ACCEPT"); if(nvram_match("fw_log_x", "drop") || nvram_match("fw_log_x", "both")) strcpy(logdrop, "logdrop"); else strcpy(logdrop, "DROP"); /* nat setting */ if(nvram_match("wan_status_t", "Connected")) // 2008.08 James. nat_setting(wan_if, wan_ip, lan_if, lan_ip, logaccept, logdrop); /* Filter setting */ filter_setting(wan_if, wan_ip, lan_if, lan_ip, logaccept, logdrop); /* Trigger port setting */ porttrigger_setting(); #ifdef WEBSTRFILTER/* Cherry Cho added in 2007/12/28. */ #if !ADDRULE if(web_filter()) printf("Fail to add web filter!!\n"); #endif #endif /* Add max conntrack as 4096, thanks for Oleg */ if ((fp=fopen("/proc/sys/net/ipv4/ip_conntrack_max", "r+"))) { if (nvram_get("misc_conntrack_x")==NULL) fputs("4096", fp); else fputs(nvram_safe_get("misc_conntrack_x"), fp); fclose(fp); } #ifdef XBOX_SUPPORT if( (fp=fopen("/proc/sys/net/ipv4/ip_conntrack_udp_timeouts", "r+")) ){ fprintf(fp, "%d %d", 65, 180); fclose(fp); } else perror("/proc/sys/net/ipv4/ip_conntrack_udp_timeouts"); #endif if( (fp=fopen("/proc/sys/net/ipv4/ip_forward", "r+")) ){ fputc('1', fp); fclose(fp); } else perror("/proc/sys/net/ipv4/ip_forward"); return 0; } int portmapping_main(int argc, char *argv[]) { char actionname[32], portname[32], ipname[32]; // Check wan interface // argv[1] = Set or Unset // argv[2] = Port // argv[3] = IP // argv[4] = Item sprintf(actionname, "4_MappedAction_%s", argv[4]); sprintf(ipname, "4_MappedIP_%s", argv[4]); sprintf(portname, "4_MappedInPort_%s", argv[4]); if (strcmp(argv[1], "Set")==0) { nvram_set(actionname, argv[1]); nvram_set(portname, argv[2]); nvram_set(ipname, argv[3]); } else { nvram_set(actionname, argv[1]); } // 2008.03 James. { //if (nvram_match("wan_proto", "pppoe")) if(nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "pptp") || nvram_match("wan_proto", "l2tp") #ifdef CDMA // HSDPA || strcmp(nvram_safe_get("hsdpa_product"), "") != 0 #endif ) // 2008.03 James. } { start_firewall_ex("ppp0", "", "br0", ""); } else { start_firewall_ex("eth0", "", "br0", ""); } return 0; } /* #ifdef USB_SUPPORT void write_ftp_banip(FILE *fp) { char *ip; int i; g_buf_init(); foreach_x("usb_bannum_x") { ip = general_conv("usb_ftpbanip_x", i); fprintf(fp, "ban=%s\n", ip); } } void write_ftp_userlist(FILE *fp) { char *user, *pass, *max, *rights; int i, maxuser; char passwd[32]; char dir[64]; g_buf_init(); mkdir_if_none("/tmp/harddisk/ftp_pub"); mkdir_if_none("/tmp/harddisk/ftp_pvt"); foreach_x("usb_ftpnum_x") { user = general_conv("usb_ftpusername_x", i); pass = general_conv("usb_ftppasswd_x", i); max = general_conv("usb_ftpmaxuser_x", i); rights = general_conv("usb_ftprights_x", i); if (strlen(max)==0) maxuser=0; else maxuser=atoi(max); if (strlen(pass)==0) strcpy(passwd, "*"); else strcpy(passwd, pass); if (strcmp(rights, "Private")==0) { fprintf(fp, "user=%s %s /ftp_pvt/%s/ %d A\n", user, passwd, user, maxuser); sprintf(dir, "/tmp/harddisk/ftp_pvt/%s", user); mkdir_if_none(dir); } else if (strcmp(rights, "Private(WO)")==0) { fprintf(fp, "user=%s %s /ftp_pvt/%s/ %d U\n", user, passwd, user, maxuser); sprintf(dir, "/tmp/harddisk/ftp_pvt/%s", user); mkdir_if_none(dir); } else if (strcmp(rights, "Read/Write/Erase")==0) fprintf(fp, "user=%s %s /ftp_pub/ %d A\n", user, passwd, maxuser); else if (strcmp(rights, "Read/Write")==0) fprintf(fp, "user=%s %s /ftp_pub/ %d DUM\n", user, passwd, maxuser); else if (strcmp(rights, "Read Only")==0) fprintf(fp, "user=%s %s /ftp_pub/ %d DM\n", user, passwd, maxuser); else if (strcmp(rights, "Write Only")==0) fprintf(fp, "user=%s %s /ftp_pub/ %d U\n", user, passwd, maxuser); else fprintf(fp, "user=%s %s /ftp_pub/ %d -\n", user, passwd, maxuser); } } #endif */ #endif #ifdef WEBSTRFILTER/* Cherry Cho added in 2007/12/27. */ int web_filter() { netconf_filter_t entry; // 2009.06 James. netconf_filter_t *rule; int i, j, ret = 0, addFilter = 0; char nvname[36]; char *activeDate, *activeTime; uint days[2] = {8, 8}; /* days[0]: start days[1]: end 0: Sunday 1: Monday 6:Saturday*/ uint activeTimeStart, activeTimeEnd; activeDate = nvram_safe_get("url_date_x"); activeTime = nvram_safe_get("url_time_x"); activeTimeStart=(((activeTime[0]-'0')*10+(activeTime[1]-'0'))*60 + (activeTime[2]-'0')*10 + (activeTime[3]-'0'))*60; activeTimeEnd=(((activeTime[4]-'0')*10+(activeTime[5]-'0'))*60 + (activeTime[6]-'0')*10 + (activeTime[7]-'0'))*60; if (nvram_match("url_enable_x", "1")){ for(j=0; j<7; j++){ if(activeDate[j] == '1'){ if(days[0]== 8){ days[0] = j; days[1] = j; } else days[1] = j; if(j==6) addFilter = 1; } else if((activeDate[j] == '0') && days[0]!= 8){ addFilter = 1; } if(addFilter){ for(i=0; i=0 && days[0]<=6) && (days[1]>=0 && days[1]<=6)){ rule->match.days[0] = days[0]; rule->match.days[1] = days[1]; } if((activeTimeStart>=0 && activeTimeStart<=(24 * 60 * 60)) && (activeTimeEnd>=0 && activeTimeEnd<=(24 * 60 * 60))){ rule->match.secs[0] = activeTimeStart; rule->match.secs[1] = activeTimeEnd; } memset(nvname, 0x0, 36); sprintf(nvname, "url_keyword_x%d", i); strcpy(rule->match.module_name, "webstr"); strncpy(rule->match.webstr_info.string, nvram_safe_get(nvname), 256); rule->match.webstr_info.invert = 0; rule->match.webstr_info.len = strlen(nvram_safe_get(nvname)); rule->match.webstr_info.type = NETCONF_WEBSTR_URL; rule->target = NETCONF_DROP; rule->dir = NETCONF_FORWARD; ret = netconf_add_fw((netconf_fw_t *)rule); } days[0] = 8; /* Reset values of days[0] and days[1] */ days[1] = 8; addFilter = 0; } } } return ret; } #endif