99#include <unistd.h>
1010#include <sys/socket.h>
1111#include <errno.h>
12+ #include <limits.h>
13+ #include <libgen.h>
1214
13- static const char * ENV_NAME = "SANDBOX_BANNED_HOSTS" ;
15+ static const char * BANNED_FILE_NAME = ".SANDBOX_BANNED_HOSTS" ;
16+
17+ /**
18+ * 从 .so 文件所在目录读取 .SANDBOX_BANNED_HOSTS 文件内容
19+ * 返回 malloc 出的字符串(需 free),读取失败则返回空字符串
20+ */
21+ static char * load_banned_hosts () {
22+ Dl_info info ;
23+ if (dladdr ((void * )load_banned_hosts , & info ) == 0 || !info .dli_fname ) {
24+ fprintf (stderr , "[sandbox] ⚠️ Unable to locate shared object path — allowing all hosts\n" );
25+ return strdup ("" );
26+ }
27+
28+ char so_path [PATH_MAX ];
29+ strncpy (so_path , info .dli_fname , sizeof (so_path ));
30+ so_path [sizeof (so_path ) - 1 ] = '\0' ;
31+
32+ char * dir = dirname (so_path );
33+ char file_path [PATH_MAX ];
34+ snprintf (file_path , sizeof (file_path ), "%s/%s" , dir , BANNED_FILE_NAME );
35+
36+ FILE * fp = fopen (file_path , "r" );
37+ if (!fp ) {
38+ fprintf (stderr , "[sandbox] ⚠️ Cannot open %s — allowing all hosts\n" , file_path );
39+ return strdup ("" );
40+ }
41+
42+ char * buf = malloc (4096 );
43+ if (!buf ) {
44+ fclose (fp );
45+ fprintf (stderr , "[sandbox] ⚠️ Memory allocation failed — allowing all hosts\n" );
46+ return strdup ("" );
47+ }
48+
49+ size_t len = fread (buf , 1 , 4095 , fp );
50+ buf [len ] = '\0' ;
51+ fclose (fp );
52+ return buf ;
53+ }
1454
1555/**
1656 * 精确匹配黑名单
17- * target: 待检测字符串
18- * env_val: 逗号分隔的黑名单列表
19- * 返回 1 = 匹配,0 = 不匹配
2057 */
2158static int match_env_patterns (const char * target , const char * env_val ) {
2259 if (!target || !env_val || !* env_val ) return 0 ;
@@ -33,7 +70,6 @@ static int match_env_patterns(const char *target, const char *env_val) {
3370
3471 if (* token ) {
3572 regex_t regex ;
36- // 精确匹配,加 ^ 和 $,忽略大小写
3773 char fullpattern [512 ];
3874 snprintf (fullpattern , sizeof (fullpattern ), "^%s$" , token );
3975
@@ -48,7 +84,6 @@ static int match_env_patterns(const char *target, const char *env_val) {
4884 fprintf (stderr , "[sandbox] ⚠️ Invalid regex '%s' — allowing host by default\n" , token );
4985 }
5086 }
51-
5287 token = strtok (NULL , "," );
5388 }
5489
@@ -62,15 +97,16 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
6297 if (!real_connect )
6398 real_connect = dlsym (RTLD_NEXT , "connect" );
6499
65- const char * banned_env = getenv (ENV_NAME );
100+ static char * banned_env = NULL ;
101+ if (!banned_env ) banned_env = load_banned_hosts ();
66102
67103 char ip [INET6_ADDRSTRLEN ] = {0 };
68104 if (addr -> sa_family == AF_INET )
69105 inet_ntop (AF_INET , & ((struct sockaddr_in * )addr )-> sin_addr , ip , sizeof (ip ));
70106 else if (addr -> sa_family == AF_INET6 )
71107 inet_ntop (AF_INET6 , & ((struct sockaddr_in6 * )addr )-> sin6_addr , ip , sizeof (ip ));
72108
73- if (banned_env && match_env_patterns (ip , banned_env )) {
109+ if (banned_env && * banned_env && match_env_patterns (ip , banned_env )) {
74110 fprintf (stderr , "[sandbox] 🚫 Access to host %s is banned\n" , ip );
75111 errno = EACCES ;
76112 return -1 ;
@@ -87,12 +123,13 @@ int getaddrinfo(const char *node, const char *service,
87123 if (!real_getaddrinfo )
88124 real_getaddrinfo = dlsym (RTLD_NEXT , "getaddrinfo" );
89125
90- const char * banned_env = getenv (ENV_NAME );
126+ static char * banned_env = NULL ;
127+ if (!banned_env ) banned_env = load_banned_hosts ();
91128
92- if (banned_env && node && match_env_patterns (node , banned_env )) {
129+ if (banned_env && * banned_env && node && match_env_patterns (node , banned_env )) {
93130 fprintf (stderr , "[sandbox] 🚫 Access to host %s is banned\n" , node );
94- return EAI_FAIL ; // 模拟 DNS 失败
131+ return EAI_FAIL ;
95132 }
96133
97134 return real_getaddrinfo (node , service , hints , res );
98- }
135+ }
0 commit comments