From 8b514106d7fa6e544d1eeb6155b47a039f21693d Mon Sep 17 00:00:00 2001 From: aixiao Date: Fri, 29 May 2020 11:09:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AC=A1=E6=8F=90=E4=BA=A4,=E6=9C=AA?= =?UTF-8?q?=E5=A4=9A=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 16 ++ README.md | 19 ++ ais.c | 693 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ais.conf | 3 + ais.h | 6 + conf.c | 150 ++++++++++++ conf.h | 19 ++ info.sh | 8 + start.sh | 11 + stop.sh | 8 + 10 files changed, 933 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 ais.c create mode 100644 ais.conf create mode 100644 ais.h create mode 100644 conf.c create mode 100644 conf.h create mode 100644 info.sh create mode 100644 start.sh create mode 100644 stop.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..abdbfba --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +CROSS_COMPILE ?= +CC := $(CROSS_COMPILE)gcc +STRIP := $(CROSS_COMPILE)strip +CFLAGS += -g -O2 -Wall +LIBS = -static +OBJ := ais + +all: conf.o ais.o + $(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS) +.c.o: + $(CC) $(CFLAGS) -c $< $(LIBS) + +clean: + rm -rf *.o + rm $(OBJ) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c94b667 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# AIS + 修改自mproxy(https://github.com/examplecode/mproxy), 作为CProxy服务端. 仅代理TCP + 支持客户端IP白名单 + +# 参数 + Usage: + -l specifyed local listen port + -h specifyed next hop server name + -d run as daemon + -E <0-128> encode data when forwarding data + -D <0-128> decode data when receiving data + +# 配置文件 + global { + // 白名单IP段, 判断前两段IP空格隔开冒号结尾 + IP_SEGMENT= 115.60 115.61 115.62 223.88; + } + + \ No newline at end of file diff --git a/ais.c b/ais.c new file mode 100644 index 0000000..5d3f629 --- /dev/null +++ b/ais.c @@ -0,0 +1,693 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ais.h" +#include "conf.h" + +//#define DEBUG 1 +#define BUF_SIZE 8192 + +#define READ 0 +#define WRITE 1 + +#define DEFAULT_LOCAL_PORT 8080 +#define DEFAULT_REMOTE_PORT 8081 +#define SERVER_SOCKET_ERROR -1 +#define SERVER_SETSOCKOPT_ERROR -2 +#define SERVER_BIND_ERROR -3 +#define SERVER_LISTEN_ERROR -4 +#define CLIENT_SOCKET_ERROR -5 +#define CLIENT_RESOLVE_ERROR -6 +#define CLIENT_CONNECT_ERROR -7 +#define CREATE_PIPE_ERROR -8 +#define BROKEN_PIPE_ERROR -9 +#define HEADER_BUFFER_FULL -10 +#define BAD_HTTP_PROTOCOL -11 + +#define MAX_HEADER_SIZE 8192 + +#if defined(OS_ANDROID) +#include + +#define LOG(fmt...) __android_log_print(ANDROID_LOG_DEBUG,__FILE__,##fmt) + +#else +#define LOG(fmt...) do { fprintf(stderr,"%s %s ",__DATE__,__TIME__); fprintf(stderr, ##fmt); } while(0) +#endif + +char remote_host[128]; +int remote_port; +int local_port; + +int server_sock; +int client_sock; +int remote_sock; + +char *header_buffer; +int sslEncodeCode; + +enum { + FLG_NONE = 0, /* 正常数据流不进行编解码 */ + R_C_DEC = 1, /* 读取客户端数据仅进行解码 */ + W_S_ENC = 2 /* 发送到服务端进行编码 */ +}; + +static int io_flag; /* 网络io的一些标志位 */ +static int m_pid; /* 保存主进程id */ + +void server_loop(); +void stop_server(); +void handle_client(int client_sock, struct sockaddr_in client_addr); +void forward_header(int destination_sock); +void forward_data(int source_sock, int destination_sock); +void rewrite_header(); +int send_data(int socket, char *buffer, int len); +int receive_data(int socket, char *buffer, int len); +void hand_mproxy_info_req(int sock, char *header_buffer); +void get_info(char *output); +const char *get_work_mode(); +int create_connection(); +int _main(int argc, char *argv[]); + +ssize_t readLine(int fd, void *buffer, size_t n) +{ + ssize_t numRead; + size_t totRead; + char *buf; + char ch; + + if (n <= 0 || buffer == NULL) { + errno = EINVAL; + return -1; + } + + buf = buffer; + + totRead = 0; + for (;;) { + numRead = receive_data(fd, &ch, 1); + + if (numRead == -1) { + if (errno == EINTR) + continue; + else + return -1; /* 未知错误 */ + + } else if (numRead == 0) { /* EOF */ + if (totRead == 0) /* No bytes read; return 0 */ + return 0; + else /* Some bytes read; add '\0' */ + break; + + } else { + + if (totRead < n - 1) { /* Discard > (n - 1) bytes */ + totRead++; + *buf++ = ch; + } + + if (ch == '\n') + break; + } + } + + *buf = '\0'; + return totRead; +} + +int read_header(int fd, void *buffer) +{ + // bzero(header_buffer,sizeof(MAX_HEADER_SIZE)); + memset(header_buffer, 0, MAX_HEADER_SIZE); + char line_buffer[2048]; + char *base_ptr = header_buffer; + + for (;;) { + memset(line_buffer, 0, 2048); + + int total_read = readLine(fd, line_buffer, 2048); + if (total_read <= 0) { + return CLIENT_SOCKET_ERROR; + } + //防止header缓冲区蛮越界 + if (base_ptr + total_read - header_buffer <= MAX_HEADER_SIZE) { + strncpy(base_ptr, line_buffer, total_read); + base_ptr += total_read; + } else { + return HEADER_BUFFER_FULL; + } + + //读到了空行,http头结束 + if (strcmp(line_buffer, "\r\n") == 0 || strcmp(line_buffer, "\n") == 0) { + break; + } + + } + return 0; + +} + +void extract_server_path(const char *header, char *output) +{ + char *p = strstr(header, "GET /"); + if (p) { + char *p1 = strchr(p + 4, ' '); + strncpy(output, p + 4, (int)(p1 - p - 4)); + } + +} + +int extract_host(const char *header) +{ + + char *_p = strstr(header, "CONNECT"); /* 在 CONNECT 方法中解析 隧道主机名称及端口号 */ + if (_p) { + char *_p1 = strchr(_p, ' '); + + char *_p2 = strchr(_p1 + 1, ':'); + char *_p3 = strchr(_p1 + 1, ' '); + + if (_p2) { + char s_port[10]; + bzero(s_port, 10); + + strncpy(remote_host, _p1 + 1, (int)(_p2 - _p1) - 1); + strncpy(s_port, _p2 + 1, (int)(_p3 - _p2) - 1); + remote_port = atoi(s_port); + + } else { + strncpy(remote_host, _p1 + 1, (int)(_p3 - _p1) - 1); + remote_port = 80; + } + + return 0; + } + + char *p = strstr(header, "Host:"); + if (!p) { + return BAD_HTTP_PROTOCOL; + } + char *p1 = strchr(p, '\n'); + if (!p1) { + return BAD_HTTP_PROTOCOL; + } + + char *p2 = strchr(p + 5, ':'); /* 5是指'Host:'的长度 */ + + if (p2 && p2 < p1) { + + int p_len = (int)(p1 - p2 - 1); + char s_port[p_len]; + strncpy(s_port, p2 + 1, p_len); + s_port[p_len] = '\0'; + remote_port = atoi(s_port); + + int h_len = (int)(p2 - p - 5 - 1); + strncpy(remote_host, p + 5 + 1, h_len); //Host: + //assert h_len < 128; + remote_host[h_len] = '\0'; + } else { + int h_len = (int)(p1 - p - 5 - 1 - 1); + strncpy(remote_host, p + 5 + 1, h_len); + //assert h_len < 128; + remote_host[h_len] = '\0'; + remote_port = 80; + } + return 0; +} + +/* 响应隧道连接请求 */ +int send_tunnel_ok(int client_sock) +{ + char *resp = "HTTP/1.1 200 Connection Established\r\n\r\n"; + int len = strlen(resp); + char buffer[len + 1]; + strcpy(buffer, resp); + if (send_data(client_sock, buffer, len) < 0) { + perror("Send http tunnel response failed\n"); + return -1; + } + return 0; +} + +//返回mproxy的运行基本信息 +void hand_mproxy_info_req(int sock, char *header) +{ + char server_path[255]; + char response[8192]; + extract_server_path(header, server_path); + + LOG("server path:%s\n", server_path); + char info_buf[1024]; + get_info(info_buf); + sprintf(response, "HTTP/1.0 200 OK\nServer: AIS/0.1\n\ + Content-type: text/html; charset=utf-8\n\n\ + \ +
%s
\ + \n", info_buf); + + write(sock, response, strlen(response)); + +} + +/* 获取运行的基本信息输出到指定的缓冲区 */ +void get_info(char *output) +{ + int pos = 0; + char line_buffer[512]; + sprintf(line_buffer, "======= AIS (v0.1) ========\n"); + int len = strlen(line_buffer); + memcpy(output, line_buffer, len); + pos += len; + + sprintf(line_buffer, "%s\n", get_work_mode()); + len = strlen(line_buffer); + memcpy(output + pos, line_buffer, len); + pos += len; + + if (strlen(remote_host) > 0) { + sprintf(line_buffer, "start server on %d and next hop is %s:%d\n", local_port, remote_host, remote_port); + } else { + sprintf(line_buffer, "start server on %d\n", local_port); + } + + len = strlen(line_buffer); + memcpy(output + pos, line_buffer, len); + pos += len; + + output[pos] = '\0'; + +} + +const char *get_work_mode() +{ + + if (strlen(remote_host) == 0) { + if (io_flag == FLG_NONE) { + return "start as normal http proxy"; + } else if (io_flag == R_C_DEC) { + return "start as remote forward proxy and do decode data when recevie data"; + } + + } else { + if (io_flag == FLG_NONE) { + return "start as remote forward proxy"; + } else if (io_flag == W_S_ENC) { + return "start as forward proxy and do encode data when send data"; + } + } + + return "unknow"; + +} + +/* 处理客户端的连接 */ +void handle_client(int client_sock, struct sockaddr_in client_addr) +{ + int is_http_tunnel = 0; + if (strlen(remote_host) == 0) { /* 未指定远端主机名称从http 请求 HOST 字段中获取 */ +#ifdef DEBUG + LOG(" ============ handle new client ============\n"); + LOG(">>>Header:%s\n", header_buffer); +#endif + + if (read_header(client_sock, header_buffer) < 0) { + LOG("Read Http header failed\n"); + return; + } else { + char *p = strstr(header_buffer, "CONNECT"); /* 判断是否是http 隧道请求 */ + if (p) { + LOG("receive CONNECT request\n"); + is_http_tunnel = 1; + } + + if (strstr(header_buffer, "GET /AIS") > 0) { + LOG("====== hand AIS info request ===="); + hand_mproxy_info_req(client_sock, header_buffer); + + return; + } + + if (extract_host(header_buffer) < 0) { + LOG("Cannot extract host field,bad http protrotol"); + return; + } + LOG("Host:%s port: %d io_flag:%d\n", remote_host, remote_port, io_flag); + + } + } + // 打印HTTP header + printf("%s", header_buffer); + + if ((remote_sock = create_connection()) < 0) { + LOG("Cannot connect to host [%s:%d]\n", remote_host, remote_port); + return; + } + + if (fork() == 0) { // 创建子进程用于从客户端转发数据到远端socket接口 + + if (strlen(header_buffer) > 0 && !is_http_tunnel) { + forward_header(remote_sock); //普通的http请求先转发header + } + + forward_data(client_sock, remote_sock); + exit(0); + } + + if (fork() == 0) { // 创建子进程用于转发从远端socket接口过来的数据到客户端 + + if (io_flag == W_S_ENC) { + io_flag = R_C_DEC; //发送请求给服务端进行编码,读取服务端的响应则进行解码 + } else if (io_flag == R_C_DEC) { + io_flag = W_S_ENC; //接收客户端请求进行解码,那么响应客户端请求需要编码 + } + + if (is_http_tunnel) { + send_tunnel_ok(client_sock); + } + + forward_data(remote_sock, client_sock); + exit(0); + } + + close(remote_sock); + close(client_sock); +} + +void forward_header(int destination_sock) +{ + rewrite_header(); +#ifdef DEBUG + LOG("================ The Forward HEAD ================="); + LOG("%s\n", header_buffer); +#endif + + int len = strlen(header_buffer); + send_data(destination_sock, header_buffer, len); +} + +int send_data(int socket, char *buffer, int len) +{ + if (io_flag == W_S_ENC) { + int i; + for (i = 0; i < len; i++) { + buffer[i] ^= sslEncodeCode; + + } + } + + return send(socket, buffer, len, 0); +} + +int receive_data(int socket, char *buffer, int len) +{ + int n = recv(socket, buffer, len, 0); + if (io_flag == R_C_DEC && n > 0) { + int i; + for (i = 0; i < n; i++) { + buffer[i] ^= sslEncodeCode; + // printf("%d => %d\n",c,buffer[i]); + } + } + + return n; +} + +/* 代理中的完整URL转发前需改成 path 的形式 */ +void rewrite_header() +{ + char *p = strstr(header_buffer, "http://"); + char *p0 = strchr(p, '\0'); + char *p5 = strstr(header_buffer, "HTTP/"); /* "HTTP/" 是协议标识 如 "HTTP/1.1" */ + int len = strlen(header_buffer); + if (p) { + char *p1 = strchr(p + 7, '/'); + if (p1 && (p5 > p1)) { + //转换url到 path + memcpy(p, p1, (int)(p0 - p1)); + int l = len - (p1 - p); + header_buffer[l] = '\0'; + } else { + char *p2 = strchr(p, ' '); //GET http://3g.sina.com.cn HTTP/1.1 + + // printf("%s\n",p2); + memcpy(p + 1, p2, (int)(p0 - p2)); + *p = '/'; //url 没有路径使用根 + int l = len - (p2 - p) + 1; + header_buffer[l] = '\0'; + } + } +} + +void forward_data(int source_sock, int destination_sock) +{ + char buffer[BUF_SIZE]; + int n; + + while ((n = receive_data(source_sock, buffer, BUF_SIZE)) > 0) { + + send_data(destination_sock, buffer, n); + } + + shutdown(destination_sock, SHUT_RDWR); + shutdown(source_sock, SHUT_RDWR); +} + +int create_connection() +{ + struct sockaddr_in server_addr; + struct hostent *server; + int sock; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return CLIENT_SOCKET_ERROR; + } + + if ((server = gethostbyname(remote_host)) == NULL) { + errno = EFAULT; + return CLIENT_RESOLVE_ERROR; + } + LOG("======= forward request to remote host:%s port:%d ======= \n", remote_host, remote_port); + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length); + server_addr.sin_port = htons(remote_port); + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + return CLIENT_CONNECT_ERROR; + } + + return sock; +} + +int create_server_socket(int port) +{ + int server_sock, optval; + struct sockaddr_in server_addr; + + if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return SERVER_SOCKET_ERROR; + } + + optval = 1; + if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { + return SERVER_SETSOCKOPT_ERROR; + } + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + server_addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) + != 0) { + return SERVER_BIND_ERROR; + } + + if (listen(server_sock, 20) < 0) { + return SERVER_LISTEN_ERROR; + } + + return server_sock; +} + +/* 处理僵尸进程 */ +void sigchld_handler(int signal) +{ + while (waitpid(-1, NULL, WNOHANG) > 0) ; +} + +// IP段白名单 +int whitelist(char *client_ip, char (*whitelist_ip)[32]) +{ + for (int i = 1; i < WHITELIST_IP_NUM - 1; i++) { + if (strcmp(whitelist_ip[i], "\0") == 0) { // 如果字符串为空就跳出循环 + break; + } + if ((strncmp(client_ip, whitelist_ip[i], strlen(whitelist_ip[i]))) == 0) { // 对比client_ip长度, + return 1; + } + } + + return 0; +} + +void server_loop() +{ + char ipstr[128]; + char client_ip[32]; // 客户端IP + struct sockaddr_in client_addr; + socklen_t addrlen = sizeof(client_addr); + + conf *configure = (struct CONF *)malloc(sizeof(struct CONF)); + read_conf("ais.conf", configure); + printf("%s\n", configure->IP_SEGMENT); + + char whitelist_ip[WHITELIST_IP_NUM][32] = { 0 }; + split_string(configure->IP_SEGMENT, " ", whitelist_ip); + + for (int i = 1; i <= WHITELIST_IP_NUM - 1; i++) { + if (*whitelist_ip[i] != '\0') + printf("%s\n", whitelist_ip[i]); + } + //exit(0); + + while (1) { + client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addrlen); + if (client_sock > 0) { + LOG("Client Ip %s Client Port %d\n", inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, ipstr, sizeof(ipstr)), ntohs(client_addr.sin_port)); + strcpy(client_ip, inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, ipstr, sizeof(ipstr))); // 复制客户端IP到client_ip + if (whitelist(client_ip, whitelist_ip) == 0) { + LOG("非法客户端, 拒绝连接\n"); + continue; + } + } + + if (fork() == 0) { // 创建子进程处理客户端连接请求 + close(server_sock); + handle_client(client_sock, client_addr); + exit(0); + } + close(client_sock); + } + +} + +void stop_server() +{ + kill(m_pid, SIGKILL); +} + +void usage(void) +{ + printf("Usage:\n"); + printf(" -l specifyed local listen port \n"); + printf(" -h specifyed next hop server name\n"); + printf(" -d run as daemon\n"); + printf(" -E <0-128> encode data when forwarding data\n"); + printf(" -D <0-128> decode data when receiving data\n"); + exit(8); +} + +void start_server(int daemon) +{ + //初始化全局变量 + header_buffer = (char *)malloc(MAX_HEADER_SIZE); + + signal(SIGCHLD, sigchld_handler); // 防止子进程变成僵尸进程 + + if ((server_sock = create_server_socket(local_port)) < 0) { // start server + LOG("Cannot run server on %d\n", local_port); + exit(server_sock); + } + + if (daemon) { + pid_t pid; + if ((pid = fork()) == 0) { + server_loop(); + } else if (pid > 0) { + m_pid = pid; + LOG("mporxy pid is: [%d]\n", pid); + close(server_sock); + } else { + LOG("Cannot daemonize\n"); + exit(pid); + } + + } else { + server_loop(); + } + +} + +int main(int argc, char *argv[]) +{ + return _main(argc, argv); +} + +int _main(int argc, char *argv[]) +{ + local_port = DEFAULT_LOCAL_PORT; + io_flag = FLG_NONE; + sslEncodeCode = 1; + int daemon = 0; + + char info_buf[2048]; + + int opt; + char optstrs[] = ":l:f:dE:D:h?"; + char *p = NULL; + while (-1 != (opt = getopt(argc, argv, optstrs))) { + switch (opt) { + case 'l': + local_port = atoi(optarg); + break; + case 'f': + p = strchr(optarg, ':'); + if (p) { + strncpy(remote_host, optarg, p - optarg); + remote_port = atoi(p + 1); + } else { + strncpy(remote_host, optarg, strlen(remote_host)); + } + break; + case 'd': + daemon = 1; + break; + case 'E': + io_flag = W_S_ENC; + sslEncodeCode = atoi(optarg); + break; + case 'D': + io_flag = R_C_DEC; + sslEncodeCode = atoi(optarg); + + break; + case ':': + printf("\nMissing argument after: -%c\n", optopt); + usage(); + case 'h': + case '?': + printf("\nInvalid argument: %c\n", optopt); + usage(); + default: + usage(); + } + } + printf("sslEncodeCode: %d\n", sslEncodeCode); + get_info(info_buf); + LOG("%s\n", info_buf); + start_server(daemon); + return 0; +} diff --git a/ais.conf b/ais.conf new file mode 100644 index 0000000..17e635f --- /dev/null +++ b/ais.conf @@ -0,0 +1,3 @@ +global { + IP_SEGMENT= 115.60 115.61 115.62 223.88; +} diff --git a/ais.h b/ais.h new file mode 100644 index 0000000..de87bd3 --- /dev/null +++ b/ais.h @@ -0,0 +1,6 @@ +#ifndef _AIS_ +#define _AIS_ + +#define WHITELIST_IP_NUM 200 + +#endif diff --git a/conf.c b/conf.c new file mode 100644 index 0000000..aa16825 --- /dev/null +++ b/conf.c @@ -0,0 +1,150 @@ +#include "conf.h" + +/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */ +static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end) +{ + + char *p, *pn, *lineEnd; + ; + int val_len; + + while (1) { + if (content == NULL) + return NULL; + + for (; *content == ' ' || *content == '\t' || *content == '\r' || *content == '\n'; content++) ; + if (*content == '\0') + return NULL; + *var = content; + pn = strchr(content, '\n'); + p = strchr(content, '='); + if (p == NULL) { + if (pn) { + content = pn + 1; + continue; + } else + return NULL; + } + content = p; + //将变量以\0结束 + for (p--; *p == ' ' || *p == '\t'; p--) ; + *(p + 1) = '\0'; + //值的首地址 + for (content++; *content == ' ' || *content == '\t'; content++) ; + if (*content == '\0') + return NULL; + //双引号引起来的值支持换行 + if (*content == '"') { + *val_begin = content + 1; + *val_end = strstr(*val_begin, "\";"); + if (*val_end != NULL) + break; + } else + *val_begin = content; + *val_end = strchr(content, ';'); + if (pn && *val_end > pn) { + content = pn + 1; + continue; + } + break; + } + + if (*val_end) { + **val_end = '\0'; + val_len = *val_end - *val_begin; + lineEnd = *val_end; + } else { + val_len = strlen(*val_begin); + *val_end = lineEnd = *val_begin + val_len; + } + *val_end = *val_begin + val_len; + //printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin); + return lineEnd; +} + +static void parse_global_module(char *content, conf * p) +{ + char *var, *val_begin, *val_end, *lineEnd; + int val_begin_len; + + while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) { + if (strcasecmp(var, "IP_SEGMENT") == 0) { + val_begin_len = strlen(val_begin) + 1; + p->IP_SEGMENT = (char *)malloc(val_begin_len); + memset(p->IP_SEGMENT, 0, val_begin_len); + memcpy(p->IP_SEGMENT, val_begin, val_begin_len); + } + content = strchr(lineEnd + 1, '\n'); + } +} + +/* 在buff中读取模块(global http https httpdns httpudp)内容 */ +static char *read_module(char *buff, const char *module_name) +{ + int len; + char *p, *p0; + + len = strlen(module_name); + p = buff; + while (1) { + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (strncasecmp(p, module_name, len) == 0) { + p += len; + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (*p == '{') + break; + } + if ((p = strchr(p, '\n')) == NULL) + return NULL; + } + + if ((p0 = strchr(++p, '}')) == NULL) + return NULL; + return strndup(p, p0 - p); +} + +void read_conf(char *filename, conf * configure) +{ + char *buff, *global_content; + FILE *file; + long file_size; + + file = fopen(filename, "r"); + if (file == NULL) + perror("cannot open config file."); + fseek(file, 0, SEEK_END); + file_size = ftell(file); + buff = (char *)alloca(file_size + 1); + if (buff == NULL) + perror("out of memory."); + rewind(file); + fread(buff, file_size, 1, file); + fclose(file); + buff[file_size] = '\0'; + + if ((global_content = read_module(buff, "global")) == NULL) { + perror("read global module error"); + } + parse_global_module(global_content, configure); + free(global_content); +} + +void free_conf(conf * p) +{ + free(p->IP_SEGMENT); + return; +} + +void split_string(char string[], char delims[], char (*whitelist_ip)[32]) +{ + int i = 0; + char *result = NULL; + result = strtok(string, delims); + while (result != NULL) { + i++; + strcpy(whitelist_ip[i], result); + result = strtok(NULL, delims); + } +} diff --git a/conf.h b/conf.h new file mode 100644 index 0000000..7d53e50 --- /dev/null +++ b/conf.h @@ -0,0 +1,19 @@ +#ifndef CONF_H +#define CONF_H + +#include +#include +#include +#include +#include + +// 配置文件结构 +typedef struct CONF { + char *IP_SEGMENT; +} conf; + +void read_conf(char *filename, conf * configure); +void free_conf(conf * p); +void split_string(char string[], char delims[], char (*whitelist_ip)[32]); + +#endif diff --git a/info.sh b/info.sh new file mode 100644 index 0000000..90a5880 --- /dev/null +++ b/info.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# +# GET info +# date 20200526 +# + +cat info.txt | grep "Client Ip" | awk '{print $7}' | uniq -c + diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..8c79d5d --- /dev/null +++ b/start.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Start AIS +# date: 20200526 +# + +SHELL_FOLDER=$(cd "$(dirname "$0")"; pwd) #脚本所在目录 +SHELL_FOLDER=$(dirname $(readlink -f "$0")) + +${SHELL_FOLDER}/ais -l 1080 -D 128 -d &>> ${SHELL_FOLDER}/info.txt + diff --git a/stop.sh b/stop.sh new file mode 100644 index 0000000..ba99f89 --- /dev/null +++ b/stop.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# +# Stop AIS +# date 20200526 +# + +killall ais +