fix: harden intranet CUPS setup
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=CUPS Printer Driver Manager
|
||||
Documentation=https://gitee.com/yu-yon/S905L3A
|
||||
Documentation=https://git.workyai.cn/237899745/S905L3A
|
||||
After=network.target cups.service
|
||||
Wants=cups.service
|
||||
|
||||
@@ -8,10 +8,11 @@ Wants=cups.service
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/cups-driver-manager
|
||||
ExecStart=/usr/bin/python3 /opt/cups-driver-manager/driver_manager.py --port 632
|
||||
ExecStart=/usr/bin/python3 /opt/cups-driver-manager/driver_manager.py --host 0.0.0.0 --port 632
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Environment=DRIVER_MANAGER_PASSWORD=admin
|
||||
Environment=DRIVER_MANAGER_ALLOW_PRIVATE_ONLY=1
|
||||
|
||||
# 安全设置
|
||||
NoNewPrivileges=false
|
||||
|
||||
@@ -12,6 +12,7 @@ import tempfile
|
||||
import shutil
|
||||
import tarfile
|
||||
import zipfile
|
||||
import ipaddress
|
||||
from pathlib import Path
|
||||
from functools import wraps
|
||||
|
||||
@@ -29,6 +30,7 @@ ALLOWED_EXTENSIONS = {'deb', 'ppd', 'gz', 'tar', 'tgz', 'zip', 'rpm', 'sh', 'run
|
||||
# 管理员凭据(可通过环境变量设置)
|
||||
ADMIN_USERNAME = os.environ.get('DRIVER_MANAGER_USERNAME', 'admin')
|
||||
ADMIN_PASSWORD = os.environ.get('DRIVER_MANAGER_PASSWORD', 'admin')
|
||||
ALLOW_PRIVATE_ONLY = os.environ.get('DRIVER_MANAGER_ALLOW_PRIVATE_ONLY', '1').lower() not in ('0', 'false', 'no', 'off')
|
||||
|
||||
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
||||
app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH
|
||||
@@ -36,6 +38,46 @@ app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH
|
||||
# 确保上传目录存在
|
||||
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||
|
||||
@app.before_request
|
||||
def limit_private_network():
|
||||
"""默认只允许本机、链路本地和内网地址访问。"""
|
||||
if not ALLOW_PRIVATE_ONLY:
|
||||
return None
|
||||
|
||||
remote_addr = request.remote_addr or ''
|
||||
try:
|
||||
addr = ipaddress.ip_address(remote_addr)
|
||||
except ValueError:
|
||||
return Response('仅允许内网访问驱动管理器\n', 403)
|
||||
|
||||
if addr.is_loopback or addr.is_private or addr.is_link_local:
|
||||
return None
|
||||
|
||||
return Response('仅允许内网访问驱动管理器\n', 403)
|
||||
|
||||
def _is_within_directory(base_dir, target_path):
|
||||
base = os.path.realpath(base_dir)
|
||||
target = os.path.realpath(target_path)
|
||||
return os.path.commonpath([base, target]) == base
|
||||
|
||||
def safe_extract_tar(tar, path):
|
||||
"""防止恶意 tar 包写出解压目录。"""
|
||||
for member in tar.getmembers():
|
||||
target_path = os.path.join(path, member.name)
|
||||
if not _is_within_directory(path, target_path):
|
||||
raise ValueError(f'压缩包包含非法路径: {member.name}')
|
||||
if member.issym() or member.islnk():
|
||||
raise ValueError(f'压缩包包含链接文件: {member.name}')
|
||||
tar.extractall(path)
|
||||
|
||||
def safe_extract_zip(zip_ref, path):
|
||||
"""防止恶意 zip 包写出解压目录。"""
|
||||
for member in zip_ref.infolist():
|
||||
target_path = os.path.join(path, member.filename)
|
||||
if not _is_within_directory(path, target_path):
|
||||
raise ValueError(f'压缩包包含非法路径: {member.filename}')
|
||||
zip_ref.extractall(path)
|
||||
|
||||
def check_auth(username, password):
|
||||
"""验证用户名和密码"""
|
||||
return username == ADMIN_USERNAME and password == ADMIN_PASSWORD
|
||||
@@ -168,7 +210,7 @@ def install_tar_gz(filepath):
|
||||
try:
|
||||
# 解压
|
||||
with tarfile.open(filepath, 'r:gz') as tar:
|
||||
tar.extractall(extract_dir)
|
||||
safe_extract_tar(tar, extract_dir)
|
||||
results.append(('解压文件', {
|
||||
'success': True,
|
||||
'stdout': f'已解压到 {extract_dir}',
|
||||
@@ -240,7 +282,7 @@ def install_zip(filepath):
|
||||
try:
|
||||
# 解压
|
||||
with zipfile.ZipFile(filepath, 'r') as zip_ref:
|
||||
zip_ref.extractall(extract_dir)
|
||||
safe_extract_zip(zip_ref, extract_dir)
|
||||
results.append(('解压文件', {
|
||||
'success': True,
|
||||
'stdout': f'已解压到 {extract_dir}',
|
||||
|
||||
Reference in New Issue
Block a user