feat: add MAXKB_SANDBOX_PYTHON_BANNED_HOSTS env to ban host for sandbox in tools code.

This commit is contained in:
liqiang-fit2cloud 2025-11-05 16:43:17 +08:00 committed by CaptainB
parent f417a5aa39
commit 1186752027
4 changed files with 103 additions and 3 deletions

View File

@ -197,7 +197,7 @@ exec({dedent(code)!a})
file.write(_code)
os.system(f"chown {self.user}:root {exec_python_file}")
kwargs = {'cwd': BASE_DIR}
kwargs['env'] = {}
kwargs['env'] = {'LD_PRELOAD': '/opt/maxkb-app/apps/sanbox_ban_host.so'}
subprocess_result = subprocess.run(
['su', '-s', python_directory, '-c', "exec(open('" + exec_python_file + "').read())", self.user],
text=True,

View File

@ -9,11 +9,12 @@ RUN cd ui && ls -la && if [ -d "dist" ]; then exit 0; fi && \
FROM ghcr.io/1panel-dev/maxkb-base:python3.11-pg17.6 AS stage-build
COPY --chmod=700 . /opt/maxkb-app
RUN apt-get update && \
apt-get install -y --no-install-recommends gettext libexpat1-dev libffi-dev && \
apt-get install -y --no-install-recommends gcc g++ gettext libexpat1-dev libffi-dev && \
apt-get clean all && \
rm -rf /var/lib/apt/lists/*
WORKDIR /opt/maxkb-app
RUN rm -rf /opt/maxkb-app/ui && \
RUN gcc -shared -fPIC -o /opt/maxkb-app/apps/sanbox_ban_host.so /opt/maxkb-app/installer/sanbox_ban_host.c -ldl && \
rm -rf /opt/maxkb-app/ui && \
pip install uv --break-system-packages && \
python -m uv pip install -r pyproject.toml && \
find /opt/maxkb-app -depth \( -name ".git*" -o -name ".docker*" -o -name ".idea*" -o -name ".editorconfig*" -o -name ".prettierrc*" -o -name "README.md" -o -name "poetry.lock" -o -name "pyproject.toml" \) -exec rm -rf {} + && \

View File

@ -47,6 +47,7 @@ ENV PATH=/opt/py3/bin:$PATH \
MAXKB_SANDBOX=1 \
MAXKB_SANDBOX_PYTHON_PACKAGE_PATHS="/opt/py3/lib/python3.11/site-packages,/opt/maxkb-app/sandbox/python-packages,/opt/maxkb/python-packages" \
MAXKB_SANDBOX_PYTHON_BANNED_KEYWORDS="subprocess.,system(,exec(,execve(,pty.,eval(,compile(,shutil.,input(,__import__" \
MAXKB_SANDBOX_PYTHON_BANNED_HOSTS="127.0.0.1,localhost" \
MAXKB_ADMIN_PATH=/admin
EXPOSE 6379

98
sanbox_ban_host.c Normal file
View File

@ -0,0 +1,98 @@
#define _GNU_SOURCE
#include <dlfcn.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#include <unistd.h>
static const char *ENV_NAME = "MAXKB_SANDBOX_PYTHON_BANNED_HOSTS";
static int match_env_patterns(const char *target, const char *env_val) {
if (!target || !env_val || !*env_val) return 0;
char *patterns = strdup(env_val);
char *token = strtok(patterns, ",");
int matched = 0;
while (token) {
// 去掉前后空格
while (*token == ' ' || *token == '\t') token++;
char *end = token + strlen(token) - 1;
while (end > token && (*end == ' ' || *end == '\t')) *end-- = '\0';
if (*token) {
regex_t regex;
if (regcomp(&regex, token, REG_EXTENDED | REG_NOSUB) == 0) {
if (regexec(&regex, target, 0, NULL, 0) == 0) {
matched = 1;
regfree(&regex);
break;
}
regfree(&regex);
}
}
token = strtok(NULL, ",");
}
free(patterns);
return matched;
}
/**
* connect() IP 访
*/
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
static int (*real_connect)(int, const struct sockaddr *, socklen_t) = NULL;
static char *banned_env = NULL;
static int initialized = 0;
if (!real_connect)
real_connect = dlsym(RTLD_NEXT, "connect");
if (!initialized) {
banned_env = getenv(ENV_NAME);
initialized = 1;
if (banned_env)
fprintf(stderr, "[ban] Loaded banned hosts: %s\n", banned_env);
}
if (!banned_env || !*banned_env)
return real_connect(sockfd, addr, addrlen);
char ip[INET6_ADDRSTRLEN] = {0};
if (addr->sa_family == AF_INET) {
inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr, ip, sizeof(ip));
} else if (addr->sa_family == AF_INET6) {
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr, ip, sizeof(ip));
}
if (match_env_patterns(ip, banned_env)) {
fprintf(stderr, "Access to host %s is banned for sandbox\n", ip);
return -1;
}
return real_connect(sockfd, addr, addrlen);
}
/**
* getaddrinfo()
*/
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res) {
static int (*real_getaddrinfo)(const char *, const char *,
const struct addrinfo *, struct addrinfo **) = NULL;
if (!real_getaddrinfo)
real_getaddrinfo = dlsym(RTLD_NEXT, "getaddrinfo");
const char *banned_env = getenv(ENV_NAME);
if (banned_env && node && match_env_patterns(node, banned_env)) {
fprintf(stderr, "Access to host %s is banned for sandbox\n", node);
return EAI_FAIL; // 模拟 DNS 失败
}
return real_getaddrinfo(node, service, hints, res);
}