/* * Module_Firewall.c * * Created on: 2022/12/9 * Author: folus */ #include "yuarel.h" #include "define.h" enum { TMR_IDX_CONFIG, TMR_IDX_CNT }; #define is_error(ptr) ((unsigned long)ptr > (unsigned long)-4000L) #define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0])) #define PASS 1 #define FAIL -1 #define YES 1 #define NO 0 #define ON 1 #define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)), __LINE__, __FUNCTION__, ##args) #define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)), __LINE__, __FUNCTION__, ##args) #define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)), __LINE__, __FUNCTION__, ##args) struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct timespec tmr[TMR_IDX_CNT]; uint8_t natInterface = 0; struct FirewallPresentSetting { unsigned char isEnalbleFirewall; // 0: Disable 1: Enable unsigned char FirewallAcceptAddr[10][128]; // Max accepted server address is 10 }firewallPresentInfo; /** * * @param fmt * @return */ int StoreLogMsg(const char *fmt, ...) { char Buf[4096+256]; char buffer[4096]; time_t CurrentTime; struct tm *tm; va_list args; va_start(args, fmt); int rc = vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); memset(Buf,0,sizeof(Buf)); CurrentTime = time(NULL); tm=localtime(&CurrentTime); sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d]%s\" >> /Storage/SystemLog/[%04d.%02d]Firewall_SystemLog", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec, buffer, tm->tm_year+1900,tm->tm_mon+1); #ifdef SystemLogMessage system(Buf); #endif #ifdef ConsloePrintLog printf("[%04d.%02d.%02d %02d:%02d:%02d] - %s", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec, buffer); #endif return rc; } /** * * @return */ int InitShareMemory() { int result = PASS; int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n"); result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n"); result = FAIL; } else {} //creat ShmStatusCodeData if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { DEBUG_ERROR("shmget ShmStatusCodeData NG\n"); result = FAIL; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmStatusCodeData NG\n"); result = FAIL; } else {} return result; } /** * * @param cmd * @return */ int runShellCmd(const char*cmd) { int result = FAIL; char buf[256]; FILE *fp; fp = popen(cmd, "r"); if(fp != NULL) { while(fgets(buf, sizeof(buf), fp) != NULL) { DEBUG_INFO("%s\n", buf); } result = PASS; } pclose(fp); return result; } /** * * @param timer */ void refreshStartTimer(struct timespec *timer) { clock_gettime(CLOCK_MONOTONIC, timer); } /** * * @param timer * @return */ int getDiffSecNow(struct timespec timer) { struct timespec timerNow; clock_gettime(CLOCK_MONOTONIC, &timerNow); return (int)((((unsigned long)(timerNow.tv_sec - timer.tv_sec) * 1000) + ((unsigned long)((timerNow.tv_nsec / 1000000) - (timer.tv_nsec / 1000000))))/1000); } /** * * @return */ unsigned int isKernelSupportNAT() { unsigned int result = NO; unsigned int version = 0; FILE *fp; char cmd[256]; char buf[512]; // Get IP address & net mask strcpy(cmd, "uname -v"); fp = popen(cmd, "r"); if(fp != NULL) { if(fgets(buf, sizeof(buf), fp) != NULL) { sscanf(buf, "#%d", &version); //DEBUG_INFO("Kernel version: %d\n", version); if(version >= 30) result = YES; } } pclose(fp); return result; } /** * * @return */ int firewallConfig() { struct yuarel url; char urlBuf[512] = {0}; char cmdBuf[512] = {0}; runShellCmd("/sbin/iptables -F"); if(ShmSysConfigAndInfo->SysConfig.isEnalbleFirewall) { // Other address mandatory configure runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d 192.168.0.0/255.255.0.0 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d 8.8.8.8/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d 180.76.76.76/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d evsocket.phihong.com.tw/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d ocpp.phihong.com.tw/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d ftp.phihong.com.tw/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d time.windows.com/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d cn.ntp.org.cn/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d tock.stdtime.gov.tw/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d 0.europe.pool.ntp.org/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d curl.haxx.se/255.255.255.255 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s 192.168.0.0/255.255.0.0 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s 8.8.8.8/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s 180.76.76.76/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s evsocket.phihong.com.tw/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s ocpp.phihong.com.tw/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s ftp.phihong.com.tw/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s time.windows.com/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s cn.ntp.org.cn/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s tock.stdtime.gov.tw/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s 0.europe.pool.ntp.org/255.255.255.255 -d any/0 -j ACCEPT"); runShellCmd("/sbin/iptables -A INPUT -p all -s curl.haxx.se/255.255.255.255 -d any/0 -j ACCEPT"); // Back end server URL parse if((ShmSysConfigAndInfo->SysConfig.OcppServerURL != NULL) && (strcmp((const char *)ShmSysConfigAndInfo->SysConfig.OcppServerURL,"") != 0) ) { memcpy(urlBuf, ShmSysConfigAndInfo->SysConfig.OcppServerURL, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.OcppServerURL)); if(yuarel_parse(&url, urlBuf) != -1) { DEBUG_INFO("Add %s to allow rule.\n", url.host); sprintf(cmdBuf, "/sbin/iptables -A OUTPUT -p all -s any/0 -d %s/255.255.255.255 -j ACCEPT", url.host); runShellCmd(cmdBuf); sprintf(cmdBuf, "/sbin/iptables -A INPUT -p all -s %s/255.255.255.255 -d any/0 -j ACCEPT", url.host); runShellCmd(cmdBuf); } } if((ShmSysConfigAndInfo->SysConfig.MaintainServerURL != NULL) && (strcmp((const char *)ShmSysConfigAndInfo->SysConfig.MaintainServerURL,"") != 0) ) { memcpy(urlBuf, ShmSysConfigAndInfo->SysConfig.MaintainServerURL, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.MaintainServerURL)); if(yuarel_parse(&url, urlBuf) != -1) { DEBUG_INFO("Add %s to allow rule.\n", url.host); sprintf(cmdBuf, "/sbin/iptables -A OUTPUT -p all -s any/0 -d %s/255.255.255.255 -j ACCEPT", url.host); runShellCmd(cmdBuf); sprintf(cmdBuf, "/sbin/iptables -A INPUT -p all -s %s/255.255.255.255 -d any/0 -j ACCEPT", url.host); runShellCmd(cmdBuf); } } // User custom configure address for(uint8_t idx=0;idxSysConfig.FirewallAcceptAddr);idx++) { if(strlen((char*)ShmSysConfigAndInfo->SysConfig.FirewallAcceptAddr[idx]) > 0) { DEBUG_INFO("Add %s to allow rule.\n", ShmSysConfigAndInfo->SysConfig.FirewallAcceptAddr[idx]); sprintf(cmdBuf, "/sbin/iptables -A OUTPUT -p all -s any/0 -d %s/255.255.255.255 -j ACCEPT", ShmSysConfigAndInfo->SysConfig.FirewallAcceptAddr[idx]); runShellCmd(cmdBuf); sprintf(cmdBuf, "/sbin/iptables -A INPUT -p all -s %s/255.255.255.255 -d any/0 -j ACCEPT", ShmSysConfigAndInfo->SysConfig.FirewallAcceptAddr[idx]); runShellCmd(cmdBuf); } } // Deny any address runShellCmd("/sbin/iptables -A OUTPUT -p all -s any/0 -d any/0 -j DROP"); runShellCmd("/sbin/iptables -A INPUT -p all -s any/0 -d any/0 -j DROP"); // List present rule runShellCmd("/sbin/iptables -L -n"); } return PASS; } /** * * @return */ int isChangeConfiguration() { int result = NO; if((firewallPresentInfo.isEnalbleFirewall != ShmSysConfigAndInfo->SysConfig.isEnalbleFirewall) || (memcmp(firewallPresentInfo.FirewallAcceptAddr, ShmSysConfigAndInfo->SysConfig.FirewallAcceptAddr, ARRAY_SIZE(firewallPresentInfo.FirewallAcceptAddr)*ARRAY_SIZE(firewallPresentInfo.FirewallAcceptAddr[0])) != 0)) { firewallPresentInfo.isEnalbleFirewall = ShmSysConfigAndInfo->SysConfig.isEnalbleFirewall; memcpy(firewallPresentInfo.FirewallAcceptAddr, ShmSysConfigAndInfo->SysConfig.FirewallAcceptAddr, ARRAY_SIZE(firewallPresentInfo.FirewallAcceptAddr)*ARRAY_SIZE(firewallPresentInfo.FirewallAcceptAddr[0])); result = YES; } return result; } /** * * @return */ int main(void) { //========================================== //Initialization share memory //========================================== if(InitShareMemory() == FAIL) { DEBUG_ERROR("InitShareMemory NG\n"); if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1; } sleep(5); return 0; } firewallPresentInfo.isEnalbleFirewall = 0xff; DEBUG_INFO("Module_Firewall version: V0.01\n"); DEBUG_INFO("Module_Firewall initialized...\n"); for(;;) { if(isChangeConfiguration()) { DEBUG_INFO("Firewall rule changed.\n"); sleep(3); firewallConfig(); } usleep(100000); } return -1; }