1+ #define _GNU_SOURCE
2+ #include <dlfcn.h>
3+ #include <netdb.h>
4+ #include <arpa/inet.h>
5+ #include <string.h>
6+ #include <stdio.h>
7+ #include <stdlib.h>
8+ #include <regex.h>
9+ #include <unistd.h>
10+
11+ static const char * ENV_NAME = "MAXKB_SANDBOX_PYTHON_BANNED_HOSTS" ;
12+
13+ static int match_env_patterns (const char * target , const char * env_val ) {
14+ if (!target || !env_val || !* env_val ) return 0 ;
15+
16+ char * patterns = strdup (env_val );
17+ char * token = strtok (patterns , "," );
18+ int matched = 0 ;
19+
20+ while (token ) {
21+ // 去掉前后空格
22+ while (* token == ' ' || * token == '\t' ) token ++ ;
23+ char * end = token + strlen (token ) - 1 ;
24+ while (end > token && (* end == ' ' || * end == '\t' )) * end -- = '\0' ;
25+
26+ if (* token ) {
27+ regex_t regex ;
28+ if (regcomp (& regex , token , REG_EXTENDED | REG_NOSUB ) == 0 ) {
29+ if (regexec (& regex , target , 0 , NULL , 0 ) == 0 ) {
30+ matched = 1 ;
31+ regfree (& regex );
32+ break ;
33+ }
34+ regfree (& regex );
35+ }
36+ }
37+
38+ token = strtok (NULL , "," );
39+ }
40+
41+ free (patterns );
42+ return matched ;
43+ }
44+
45+ /**
46+ * 拦截 connect() —— 屏蔽直接 IP 访问
47+ */
48+ int connect (int sockfd , const struct sockaddr * addr , socklen_t addrlen ) {
49+ static int (* real_connect )(int , const struct sockaddr * , socklen_t ) = NULL ;
50+ static char * banned_env = NULL ;
51+ static int initialized = 0 ;
52+
53+ if (!real_connect )
54+ real_connect = dlsym (RTLD_NEXT , "connect" );
55+
56+ if (!initialized ) {
57+ banned_env = getenv (ENV_NAME );
58+ initialized = 1 ;
59+ if (banned_env )
60+ fprintf (stderr , "[ban] Loaded banned hosts: %s\n" , banned_env );
61+ }
62+
63+ if (!banned_env || !* banned_env )
64+ return real_connect (sockfd , addr , addrlen );
65+
66+ char ip [INET6_ADDRSTRLEN ] = {0 };
67+ if (addr -> sa_family == AF_INET ) {
68+ inet_ntop (AF_INET , & ((struct sockaddr_in * )addr )-> sin_addr , ip , sizeof (ip ));
69+ } else if (addr -> sa_family == AF_INET6 ) {
70+ inet_ntop (AF_INET6 , & ((struct sockaddr_in6 * )addr )-> sin6_addr , ip , sizeof (ip ));
71+ }
72+
73+ if (match_env_patterns (ip , banned_env )) {
74+ fprintf (stderr , "Access to host %s is banned for sandbox\n" , ip );
75+ return -1 ;
76+ }
77+
78+ return real_connect (sockfd , addr , addrlen );
79+ }
80+
81+ /**
82+ * 拦截 getaddrinfo() —— 屏蔽域名解析
83+ */
84+ int getaddrinfo (const char * node , const char * service ,
85+ const struct addrinfo * hints , struct addrinfo * * res ) {
86+ static int (* real_getaddrinfo )(const char * , const char * ,
87+ const struct addrinfo * , struct addrinfo * * ) = NULL ;
88+ if (!real_getaddrinfo )
89+ real_getaddrinfo = dlsym (RTLD_NEXT , "getaddrinfo" );
90+
91+ const char * banned_env = getenv (ENV_NAME );
92+ if (banned_env && node && match_env_patterns (node , banned_env )) {
93+ fprintf (stderr , "Access to host %s is banned for sandbox\n" , node );
94+ return EAI_FAIL ; // 模拟 DNS 失败
95+ }
96+
97+ return real_getaddrinfo (node , service , hints , res );
98+ }
0 commit comments