commit 64452a7aa7eec0e590975188645234166125e1e5 Author: dongl <2725096176@qq.com> Date: Mon Jul 10 13:22:50 2023 +0800 main.cpp g++ -Wall -fPIC -shared -o net_ip_hook.so main.cpp -ldl sudo gedit /etc/environment #LD_LIBRARY_PATH #LD_PRELOAD LD_PRELOAD="/home/dongl/code/safe_test/hook.so" #LD_PRELOAD="/home/dongl/code/safe_test/net_ip_hook.so" diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..bfa2250 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.25) +project(ko_open) + +set(CMAKE_CXX_STANDARD 17) + +#add_executable(ko_open main.cpp) +add_executable(ko_open hook.bin.cpp) diff --git a/hook.bin.cpp b/hook.bin.cpp new file mode 100644 index 0000000..3b23935 --- /dev/null +++ b/hook.bin.cpp @@ -0,0 +1,273 @@ +// +// Created by dongl on 23-7-10. +// + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACCEPT 9999 +#define CONNECT 19999 + + + +// 定义指向原始open函数的函数指针 +typedef int (*file_open_func_t)(const char *pathname, int flags, ...); +static file_open_func_t original_file_open = nullptr; +static file_open_func_t file_open = nullptr; +//read +typedef ssize_t (*file_read_func_t)(int fd, void *buf, size_t nbytes); +static file_read_func_t original_file_read = nullptr; +static file_read_func_t file_read = nullptr; +// connect +typedef int (*ip_connect_fun_t)(int, const struct sockaddr *, socklen_t); +static ip_connect_fun_t original_file_connect = nullptr; +static ip_connect_fun_t file_connect = nullptr; +// accept +typedef int (*ip_accept_fun_t)(int, struct sockaddr *, socklen_t *); +static ip_accept_fun_t original_file_accept = nullptr; +static ip_accept_fun_t file_accept = nullptr; + + +// 定义原始的do_sys_open()函数指针 +//static long (*real_do_sys_open)(int dfd, const char __user *filename, int flags, umode_t mode) = nullptr; + +// 定义日志文件路径和配置文件路径的环境变量 +const char *LOG_FILE_PATH = "/home/dongl/code/safe_test/log"; +const char *CONFIG_FILE_PATH = "/home/dongl/code/safe_test/config.txt"; +const char *LOG_NET_IP_PATH = "/home/dongl/code/safe_test/net-log"; +const char *CONFIG_NET_IP_PATH = "/home/dongl/code/safe_test/net-config.txt"; + +// 将时间戳转换为字符串 +std::string Time_t2String(time_t t) { + char tmp[64] = {0}; + strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&t)); + return tmp; +} + +// 获取当前进程的可执行文件路径和名称 +size_t get_executable_path(char *processdir, char *processname, size_t len) { + char *path_end; + if (readlink("/proc/self/exe", processdir, len) <= 0) + return -1; + path_end = strrchr(processdir, '/'); + if (path_end == nullptr) + return -1; + ++path_end; + strcpy(processname, path_end); + *path_end = '\0'; + return (size_t) (path_end - processdir); +} + +// 读取配置文件并填充文件和进程集合 +void read_config_file(std::set& file_set, std::set& process_set, const char* config_name) { + // 打开配置文件 + int config_fd = original_file_open(config_name, O_RDONLY); + if (config_fd < 0) + return; + + // 读取配置文件 + char buff[4096]; + std::string data; + bool state = true; + while (original_file_read(config_fd, buff, sizeof(buff)) > 0) { + for (const auto &item: buff) { + if (item != '\n') { + data.push_back(item); + } else if (item == '\n') { + // 检查行是文件部分还是进程部分 + std::string temp = config_name == CONFIG_FILE_PATH ? "[safe_file]" : "[black_ip]"; + if (data == temp) { + state = true; + data.clear(); + continue; + } else if (data == "[safe_process]") { + state = false; + data.clear(); + continue; + } + + // 将文件或进程添加到相应的集合中 + if (state) { + file_set.insert(data); + data.clear(); + } else { + process_set.insert(data); + data.clear(); + } + } + } + } + + // 关闭配置文件 + close(config_fd); +} + +// 将文件访问日志写入日志文件 +void write_log(const std::string &pathname, int mode, const std::string &result, const char* log_name) { + char run_path[40960] = {0}; + char process_name[10240] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + std::string access_mode; + if (mode == O_RDONLY) + access_mode = "读取"; + else if (mode == ACCEPT) + access_mode = "ACCEPT"; + else if (mode == CONNECT) + access_mode = "CONNECT"; + else if (mode == O_WRONLY) + access_mode = "写入"; + else if (mode == O_RDWR) + access_mode = "读写"; + else if (mode == (O_WRONLY | O_APPEND)) + access_mode = "追加"; + + std::string log = "[" + Time_t2String(time(nullptr)) + "] " + + "<" + pathname + "> " + access_mode + " {" + process_name + ":" + run_path + "} " + result + "\n"; + int log_fd = original_file_open(log_name, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (log_fd > 0) { + write(log_fd, log.c_str(), log.size()); + close(log_fd); + } +} + +// +ssize_t read(int fd, void *buf, size_t nbytes) { + std::set file_set; + std::set process_set; + read_config_file(file_set, process_set, CONFIG_FILE_PATH); + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + // 根据fd取文件名 + char file_name[4096] = {'\0'}; + char file_path[4096] = {'\0'}; + snprintf(file_name, sizeof(file_name), "/proc/%d/fd/%d", getpid(), fd); + ssize_t ret = readlink(file_name, file_path, sizeof(file_path) - 1); + if (ret == -1) { + return original_file_read(fd, buf, nbytes); + } + + // 检查 + auto safe_file = file_set.find(file_path); + auto safe_process = process_set.find(process_name); + + // 校验 + if (safe_file != file_set.end()) { + if (safe_process != process_set.end()) { + write_log(file_path, O_RDONLY, "正常访问", LOG_FILE_PATH); + } else { + write_log(file_path, O_RDONLY, "拒绝访问", LOG_FILE_PATH); + errno = EACCES; + return original_file_read(fd, buf, 0); + } + } + return original_file_read(fd, buf, nbytes); +} + +// 判断接入的网络是否为过滤IP,如果是则提前返回 +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + // 获取链接ip + char ip[128]; + memset(ip, 0, sizeof(ip)); // ip地址 + int port = -1; // 端口号 + if (AF_INET == addr->sa_family) { + auto *sa4 = (struct sockaddr_in *) addr; + inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip)); + port = ntohs(sa4->sin_port); + printf("\nAF_INET IP===%s:%d\n", ip, port); + } + + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + // 获取黑名单ip + std::set ip_set; + std::set process_set; + read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH); + auto black_ip = ip_set.find(ip); + auto safe_process = process_set.find(process_name); + + // 比较IP 是黑名单ip + if (black_ip != ip_set.end()) { + // log ip + std::string temp; + temp.append(ip); + temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">"); + + if (safe_process != process_set.end()) { + write_log(temp, CONNECT, "允许访问", LOG_NET_IP_PATH); + return original_file_connect(sockfd, addr, addrlen); + } else { + write_log(temp, CONNECT, "拒绝访问", LOG_NET_IP_PATH); + return -1; + } + } + + return original_file_connect(sockfd, addr, addrlen); +} + +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + // 获取链接ip + char ip[128]; + memset(ip, 0, sizeof(ip)); // ip地址 + int port = -1; // 端口号 + if (AF_INET == addr->sa_family) { + auto *sa4 = (struct sockaddr_in *) addr; + inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip)); + port = ntohs(sa4->sin_port); + printf("\nAF_INET IP===%s:%d\n", ip, port); + } + + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + // 获取黑名单ip + std::set ip_set; + std::set process_set; + read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH); + auto black_ip = ip_set.find(ip); + auto safe_process = process_set.find(process_name); + + // log ip + std::string temp; + temp.append(ip); + temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">"); + + // 比较IP 是黑名单ip + if (black_ip != ip_set.end()) { + if (safe_process != process_set.end()) { + write_log(temp, ACCEPT, "允许访问",LOG_NET_IP_PATH); + return original_file_accept(sockfd, addr, addrlen); + } else { + write_log(temp, ACCEPT, "拒绝访问", LOG_NET_IP_PATH); + return -1; + } + } + + // 放行 + return original_file_accept(sockfd, addr, addrlen); +} + + + + +// 初始化函数,获取原始文件访问函数的地址并替换为拦截函数 +int main() { + original_file_open = (file_open_func_t) dlsym(RTLD_NEXT, "open"); + original_file_read = (file_read_func_t) dlsym(RTLD_NEXT, "read"); + original_file_connect = (ip_connect_fun_t) dlsym(RTLD_NEXT, "connect"); + original_file_accept = (ip_accept_fun_t) dlsym(RTLD_NEXT, "accept"); +} \ No newline at end of file diff --git a/hook.so b/hook.so new file mode 100755 index 0000000..5cc6c50 Binary files /dev/null and b/hook.so differ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..09c138b --- /dev/null +++ b/main.cpp @@ -0,0 +1,270 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACCEPT 9999 +#define CONNECT 19999 + + +// 定义指向原始文件访问函数的函数指针 +typedef int (*file_access_func_t)(const char *pathname, int mode, ...); +static file_access_func_t original_file_access = nullptr; +// 定义指向原始open函数的函数指针 +typedef int (*file_open_func_t)(const char *pathname, int flags, ...); +static file_open_func_t original_file_open = nullptr; +// 定义指向原始creat函数的函数指针 +typedef int (*file_creat_func_t)(const char *pathname, mode_t mode); +static file_creat_func_t original_file_creat = nullptr; +//read +typedef ssize_t (*file_read_func_t)(int fd, void *buf, size_t nbytes); +static file_read_func_t original_file_read = nullptr; +// connect +typedef int (*ip_connect_fun_t)(int, const struct sockaddr *, socklen_t); +static ip_connect_fun_t original_file_connect = nullptr; +// accept +typedef int (*ip_accept_fun_t)(int, struct sockaddr *, socklen_t *); +static ip_accept_fun_t original_file_accept = nullptr; + + +// 定义原始的do_sys_open()函数指针 +//static long (*real_do_sys_open)(int dfd, const char __user *filename, int flags, umode_t mode) = nullptr; + +// 定义日志文件路径和配置文件路径的环境变量 +const char *LOG_FILE_PATH = "/home/dongl/code/safe_test/log"; +const char *CONFIG_FILE_PATH = "/home/dongl/code/safe_test/config.txt"; +const char *LOG_NET_IP_PATH = "/home/dongl/code/safe_test/net-log"; +const char *CONFIG_NET_IP_PATH = "/home/dongl/code/safe_test/net-config.txt"; + +// 将时间戳转换为字符串 +std::string Time_t2String(time_t t) { + char tmp[64] = {0}; + strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&t)); + return tmp; +} + +// 获取当前进程的可执行文件路径和名称 +size_t get_executable_path(char *processdir, char *processname, size_t len) { + char *path_end; + if (readlink("/proc/self/exe", processdir, len) <= 0) + return -1; + path_end = strrchr(processdir, '/'); + if (path_end == nullptr) + return -1; + ++path_end; + strcpy(processname, path_end); + *path_end = '\0'; + return (size_t) (path_end - processdir); +} + +// 读取配置文件并填充文件和进程集合 +void read_config_file(std::set& file_set, std::set& process_set, const char* config_name) { + // 打开配置文件 + int config_fd = original_file_open(config_name, O_RDONLY); + if (config_fd < 0) + return; + + // 读取配置文件 + char buff[4096]; + std::string data; + bool state = true; + while (original_file_read(config_fd, buff, sizeof(buff)) > 0) { + for (const auto &item: buff) { + if (item != '\n') { + data.push_back(item); + } else if (item == '\n') { + // 检查行是文件部分还是进程部分 + std::string temp = config_name == CONFIG_FILE_PATH ? "[safe_file]" : "[black_ip]"; + if (data == temp) { + state = true; + data.clear(); + continue; + } else if (data == "[safe_process]") { + state = false; + data.clear(); + continue; + } + + // 将文件或进程添加到相应的集合中 + if (state) { + file_set.insert(data); + data.clear(); + } else { + process_set.insert(data); + data.clear(); + } + } + } + } + + // 关闭配置文件 + close(config_fd); +} + +// 将文件访问日志写入日志文件 +void write_log(const std::string &pathname, int mode, const std::string &result, const char* log_name) { + char run_path[40960] = {0}; + char process_name[10240] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + std::string access_mode; + if (mode == O_RDONLY) + access_mode = "读取"; + else if (mode == ACCEPT) + access_mode = "ACCEPT"; + else if (mode == CONNECT) + access_mode = "CONNECT"; + else if (mode == O_WRONLY) + access_mode = "写入"; + else if (mode == O_RDWR) + access_mode = "读写"; + else if (mode == (O_WRONLY | O_APPEND)) + access_mode = "追加"; + + std::string log = "[" + Time_t2String(time(nullptr)) + "] " + + "<" + pathname + "> " + access_mode + " {" + process_name + ":" + run_path + "} " + result + "\n"; + int log_fd = original_file_open(log_name, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (log_fd > 0) { + write(log_fd, log.c_str(), log.size()); + close(log_fd); + } +} + +// +ssize_t read(int fd, void *buf, size_t nbytes) { + std::set file_set; + std::set process_set; + read_config_file(file_set, process_set, CONFIG_FILE_PATH); + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + // 根据fd取文件名 + char file_name[4096] = {'\0'}; + char file_path[4096] = {'\0'}; + snprintf(file_name, sizeof(file_name), "/proc/%d/fd/%d", getpid(), fd); + ssize_t ret = readlink(file_name, file_path, sizeof(file_path) - 1); + if (ret == -1) { + return original_file_read(fd, buf, nbytes); + } + + // 检查 + auto safe_file = file_set.find(file_path); + auto safe_process = process_set.find(process_name); + + // 校验 + if (safe_file != file_set.end()) { + if (safe_process != process_set.end()) { + write_log(file_path, O_RDONLY, "正常访问", LOG_FILE_PATH); + } else { + write_log(file_path, O_RDONLY, "拒绝访问", LOG_FILE_PATH); + errno = EACCES; + return original_file_read(fd, buf, 0); + } + } + return original_file_read(fd, buf, nbytes); +} + +// 判断接入的网络是否为过滤IP,如果是则提前返回 +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + // 获取链接ip + char ip[128]; + memset(ip, 0, sizeof(ip)); // ip地址 + int port = -1; // 端口号 + if (AF_INET == addr->sa_family) { + auto *sa4 = (struct sockaddr_in *) addr; + inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip)); + port = ntohs(sa4->sin_port); + printf("\nAF_INET IP===%s:%d\n", ip, port); + } + + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + // 获取黑名单ip + std::set ip_set; + std::set process_set; + read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH); + auto black_ip = ip_set.find(ip); + auto safe_process = process_set.find(process_name); + + // 比较IP 是黑名单ip + if (black_ip != ip_set.end()) { + // log ip + std::string temp; + temp.append(ip); + temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">"); + + if (safe_process != process_set.end()) { + write_log(temp, CONNECT, "允许访问", LOG_NET_IP_PATH); + return original_file_connect(sockfd, addr, addrlen); + } else { + write_log(temp, CONNECT, "拒绝访问", LOG_NET_IP_PATH); + return -1; + } + } + + return original_file_connect(sockfd, addr, addrlen); +} + +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + // 获取链接ip + char ip[128]; + memset(ip, 0, sizeof(ip)); // ip地址 + int port = -1; // 端口号 + if (AF_INET == addr->sa_family) { + auto *sa4 = (struct sockaddr_in *) addr; + inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip)); + port = ntohs(sa4->sin_port); + printf("\nAF_INET IP===%s:%d\n", ip, port); + } + + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + // 获取黑名单ip + std::set ip_set; + std::set process_set; + read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH); + auto black_ip = ip_set.find(ip); + auto safe_process = process_set.find(process_name); + + // log ip + std::string temp; + temp.append(ip); + temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">"); + + // 比较IP 是黑名单ip + if (black_ip != ip_set.end()) { + if (safe_process != process_set.end()) { + write_log(temp, ACCEPT, "允许访问",LOG_NET_IP_PATH); + return original_file_accept(sockfd, addr, addrlen); + } else { + write_log(temp, ACCEPT, "拒绝访问", LOG_NET_IP_PATH); + return -1; + } + } + + // 放行 + return original_file_accept(sockfd, addr, addrlen); +} + + +// 初始化函数,获取原始文件访问函数的地址并替换为拦截函数 +__attribute__((constructor)) void init() { + original_file_access = (file_access_func_t) dlsym(RTLD_NEXT, "access"); + original_file_open = (file_open_func_t) dlsym(RTLD_NEXT, "open"); + original_file_creat = (file_creat_func_t) dlsym(RTLD_NEXT, "creat"); + original_file_read = (file_read_func_t) dlsym(RTLD_NEXT, "read"); + original_file_connect = (ip_connect_fun_t) dlsym(RTLD_NEXT, "connect"); + original_file_accept = (ip_accept_fun_t) dlsym(RTLD_NEXT, "accept"); +} \ No newline at end of file diff --git a/old.cpp b/old.cpp new file mode 100644 index 0000000..09c138b --- /dev/null +++ b/old.cpp @@ -0,0 +1,270 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACCEPT 9999 +#define CONNECT 19999 + + +// 定义指向原始文件访问函数的函数指针 +typedef int (*file_access_func_t)(const char *pathname, int mode, ...); +static file_access_func_t original_file_access = nullptr; +// 定义指向原始open函数的函数指针 +typedef int (*file_open_func_t)(const char *pathname, int flags, ...); +static file_open_func_t original_file_open = nullptr; +// 定义指向原始creat函数的函数指针 +typedef int (*file_creat_func_t)(const char *pathname, mode_t mode); +static file_creat_func_t original_file_creat = nullptr; +//read +typedef ssize_t (*file_read_func_t)(int fd, void *buf, size_t nbytes); +static file_read_func_t original_file_read = nullptr; +// connect +typedef int (*ip_connect_fun_t)(int, const struct sockaddr *, socklen_t); +static ip_connect_fun_t original_file_connect = nullptr; +// accept +typedef int (*ip_accept_fun_t)(int, struct sockaddr *, socklen_t *); +static ip_accept_fun_t original_file_accept = nullptr; + + +// 定义原始的do_sys_open()函数指针 +//static long (*real_do_sys_open)(int dfd, const char __user *filename, int flags, umode_t mode) = nullptr; + +// 定义日志文件路径和配置文件路径的环境变量 +const char *LOG_FILE_PATH = "/home/dongl/code/safe_test/log"; +const char *CONFIG_FILE_PATH = "/home/dongl/code/safe_test/config.txt"; +const char *LOG_NET_IP_PATH = "/home/dongl/code/safe_test/net-log"; +const char *CONFIG_NET_IP_PATH = "/home/dongl/code/safe_test/net-config.txt"; + +// 将时间戳转换为字符串 +std::string Time_t2String(time_t t) { + char tmp[64] = {0}; + strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&t)); + return tmp; +} + +// 获取当前进程的可执行文件路径和名称 +size_t get_executable_path(char *processdir, char *processname, size_t len) { + char *path_end; + if (readlink("/proc/self/exe", processdir, len) <= 0) + return -1; + path_end = strrchr(processdir, '/'); + if (path_end == nullptr) + return -1; + ++path_end; + strcpy(processname, path_end); + *path_end = '\0'; + return (size_t) (path_end - processdir); +} + +// 读取配置文件并填充文件和进程集合 +void read_config_file(std::set& file_set, std::set& process_set, const char* config_name) { + // 打开配置文件 + int config_fd = original_file_open(config_name, O_RDONLY); + if (config_fd < 0) + return; + + // 读取配置文件 + char buff[4096]; + std::string data; + bool state = true; + while (original_file_read(config_fd, buff, sizeof(buff)) > 0) { + for (const auto &item: buff) { + if (item != '\n') { + data.push_back(item); + } else if (item == '\n') { + // 检查行是文件部分还是进程部分 + std::string temp = config_name == CONFIG_FILE_PATH ? "[safe_file]" : "[black_ip]"; + if (data == temp) { + state = true; + data.clear(); + continue; + } else if (data == "[safe_process]") { + state = false; + data.clear(); + continue; + } + + // 将文件或进程添加到相应的集合中 + if (state) { + file_set.insert(data); + data.clear(); + } else { + process_set.insert(data); + data.clear(); + } + } + } + } + + // 关闭配置文件 + close(config_fd); +} + +// 将文件访问日志写入日志文件 +void write_log(const std::string &pathname, int mode, const std::string &result, const char* log_name) { + char run_path[40960] = {0}; + char process_name[10240] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + std::string access_mode; + if (mode == O_RDONLY) + access_mode = "读取"; + else if (mode == ACCEPT) + access_mode = "ACCEPT"; + else if (mode == CONNECT) + access_mode = "CONNECT"; + else if (mode == O_WRONLY) + access_mode = "写入"; + else if (mode == O_RDWR) + access_mode = "读写"; + else if (mode == (O_WRONLY | O_APPEND)) + access_mode = "追加"; + + std::string log = "[" + Time_t2String(time(nullptr)) + "] " + + "<" + pathname + "> " + access_mode + " {" + process_name + ":" + run_path + "} " + result + "\n"; + int log_fd = original_file_open(log_name, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (log_fd > 0) { + write(log_fd, log.c_str(), log.size()); + close(log_fd); + } +} + +// +ssize_t read(int fd, void *buf, size_t nbytes) { + std::set file_set; + std::set process_set; + read_config_file(file_set, process_set, CONFIG_FILE_PATH); + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + // 根据fd取文件名 + char file_name[4096] = {'\0'}; + char file_path[4096] = {'\0'}; + snprintf(file_name, sizeof(file_name), "/proc/%d/fd/%d", getpid(), fd); + ssize_t ret = readlink(file_name, file_path, sizeof(file_path) - 1); + if (ret == -1) { + return original_file_read(fd, buf, nbytes); + } + + // 检查 + auto safe_file = file_set.find(file_path); + auto safe_process = process_set.find(process_name); + + // 校验 + if (safe_file != file_set.end()) { + if (safe_process != process_set.end()) { + write_log(file_path, O_RDONLY, "正常访问", LOG_FILE_PATH); + } else { + write_log(file_path, O_RDONLY, "拒绝访问", LOG_FILE_PATH); + errno = EACCES; + return original_file_read(fd, buf, 0); + } + } + return original_file_read(fd, buf, nbytes); +} + +// 判断接入的网络是否为过滤IP,如果是则提前返回 +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + // 获取链接ip + char ip[128]; + memset(ip, 0, sizeof(ip)); // ip地址 + int port = -1; // 端口号 + if (AF_INET == addr->sa_family) { + auto *sa4 = (struct sockaddr_in *) addr; + inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip)); + port = ntohs(sa4->sin_port); + printf("\nAF_INET IP===%s:%d\n", ip, port); + } + + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + // 获取黑名单ip + std::set ip_set; + std::set process_set; + read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH); + auto black_ip = ip_set.find(ip); + auto safe_process = process_set.find(process_name); + + // 比较IP 是黑名单ip + if (black_ip != ip_set.end()) { + // log ip + std::string temp; + temp.append(ip); + temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">"); + + if (safe_process != process_set.end()) { + write_log(temp, CONNECT, "允许访问", LOG_NET_IP_PATH); + return original_file_connect(sockfd, addr, addrlen); + } else { + write_log(temp, CONNECT, "拒绝访问", LOG_NET_IP_PATH); + return -1; + } + } + + return original_file_connect(sockfd, addr, addrlen); +} + +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + // 获取链接ip + char ip[128]; + memset(ip, 0, sizeof(ip)); // ip地址 + int port = -1; // 端口号 + if (AF_INET == addr->sa_family) { + auto *sa4 = (struct sockaddr_in *) addr; + inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip)); + port = ntohs(sa4->sin_port); + printf("\nAF_INET IP===%s:%d\n", ip, port); + } + + // 查进程名 及 运行路径 + char run_path[4096] = {0}; + char process_name[1024] = {0}; + get_executable_path(run_path, process_name, sizeof(run_path)); + + // 获取黑名单ip + std::set ip_set; + std::set process_set; + read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH); + auto black_ip = ip_set.find(ip); + auto safe_process = process_set.find(process_name); + + // log ip + std::string temp; + temp.append(ip); + temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">"); + + // 比较IP 是黑名单ip + if (black_ip != ip_set.end()) { + if (safe_process != process_set.end()) { + write_log(temp, ACCEPT, "允许访问",LOG_NET_IP_PATH); + return original_file_accept(sockfd, addr, addrlen); + } else { + write_log(temp, ACCEPT, "拒绝访问", LOG_NET_IP_PATH); + return -1; + } + } + + // 放行 + return original_file_accept(sockfd, addr, addrlen); +} + + +// 初始化函数,获取原始文件访问函数的地址并替换为拦截函数 +__attribute__((constructor)) void init() { + original_file_access = (file_access_func_t) dlsym(RTLD_NEXT, "access"); + original_file_open = (file_open_func_t) dlsym(RTLD_NEXT, "open"); + original_file_creat = (file_creat_func_t) dlsym(RTLD_NEXT, "creat"); + original_file_read = (file_read_func_t) dlsym(RTLD_NEXT, "read"); + original_file_connect = (ip_connect_fun_t) dlsym(RTLD_NEXT, "connect"); + original_file_accept = (ip_accept_fun_t) dlsym(RTLD_NEXT, "accept"); +} \ No newline at end of file diff --git a/temp.cpp b/temp.cpp new file mode 100644 index 0000000..e69de29