fix: harden intranet CUPS setup

This commit is contained in:
2026-06-09 14:47:36 +08:00
parent 0878c71b5a
commit 2a688d2514
7 changed files with 158 additions and 112 deletions

View File

@@ -8,18 +8,18 @@
## 一、一键安装 ## 一、一键安装
### Gitee 仓库 ### Gitea 仓库
``` ```
https://gitee.com/yu-yon/S905L3A.git https://git.workyai.cn/237899745/S905L3A.git
``` ```
### 一键安装命令 ### 一键安装命令
```bash ```bash
# 方式一curl # 方式一curl
curl -fsSL https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh | bash curl -fsSL https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups.sh | bash
# 方式二wget # 方式二wget
wget -qO- https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh | bash wget -qO- https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups.sh | bash
``` ```
### 脚本功能 ### 脚本功能
@@ -38,8 +38,7 @@ wget -qO- https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh | bash
|------|------|------| |------|------|------|
| CUPS | 631 | 打印服务/Web管理界面 | | CUPS | 631 | 打印服务/Web管理界面 |
| Avahi | 5353 | mDNS/AirPrint 自动发现 | | Avahi | 5353 | mDNS/AirPrint 自动发现 |
| Samba | 445/139 | Windows SMB 打印共享 | | 驱动管理器 | 632 | 内网上传安装打印机驱动(可选) |
| LPR (xinetd) | 515 | LPR 打印协议 |
--- ---
@@ -56,19 +55,7 @@ wget -qO- https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh | bash
### 公网环境 ### 公网环境
公网环境较为复杂,可能遇到以下问题: 不建议把 CUPS 或驱动管理器直接暴露到公网。本项目默认按内网使用配置,访问范围使用 `@LOCAL`,驱动管理器也会拒绝非私有网段来源。
- Windows IPP 强制使用 HTTPS自签名证书不受信任
- SMB 445 端口可能被 ISP 阻止
- 需要在云服务器安全组开放相应端口
**公网可用方案:**
1. **LPR 协议(推荐)**
- 端口515
- 队列名:打印机名(如 PDF
- Windows 添加方式TCP/IP 打印机 → 自定义 → LPR 协议
2. **IPP + 证书信任**
- 需要将服务器证书导入 Windows 受信任的根证书
--- ---
@@ -98,9 +85,8 @@ https://服务器IP:631
| `/etc/cups/cupsd.conf` | CUPS 主配置文件 | | `/etc/cups/cupsd.conf` | CUPS 主配置文件 |
| `/etc/cups/printers.conf` | 打印机配置 | | `/etc/cups/printers.conf` | 打印机配置 |
| `/etc/cups/ssl/` | SSL 证书目录 | | `/etc/cups/ssl/` | SSL 证书目录 |
| `/etc/samba/smb.conf` | Samba 配置SMB 打印共享) |
| `/etc/xinetd.d/cups-lpd` | LPR 服务配置 |
| `/usr/share/cups/templates-zh_CN/` | 中文界面模板 | | `/usr/share/cups/templates-zh_CN/` | 中文界面模板 |
| `/opt/cups-driver-manager/` | 驱动管理器安装目录(可选) |
--- ---
@@ -114,8 +100,8 @@ Listen 0.0.0.0:631
# 允许任何主机名访问 # 允许任何主机名访问
ServerAlias * ServerAlias *
# 禁用强制加密(允许 HTTP # 内网允许 HTTP同时接受客户端主动 HTTPS
DefaultEncryption Never DefaultEncryption IfRequested
# 中文界面 # 中文界面
DefaultLanguage zh DefaultLanguage zh
@@ -123,32 +109,16 @@ DefaultLanguage zh
# 允许远程访问 # 允许远程访问
<Location /> <Location />
Order allow,deny Order allow,deny
Allow all Allow @LOCAL
</Location> </Location>
# 允许远程打印 # 允许远程打印
<Location /printers> <Location /printers>
Order allow,deny Order allow,deny
Allow all Allow @LOCAL
</Location> </Location>
``` ```
### Samba 打印配置
```ini
[global]
printing = cups
printcap name = cups
load printers = yes
[printers]
comment = All Printers
path = /var/spool/samba
printable = yes
guest ok = yes
```
---
## 七、常用命令 ## 七、常用命令
```bash ```bash
@@ -161,14 +131,8 @@ systemctl restart cups
# 查看 CUPS 日志 # 查看 CUPS 日志
tail -f /var/log/cups/error_log tail -f /var/log/cups/error_log
# 重启 Samba
systemctl restart smbd nmbd
# 重启 LPR 服务
systemctl restart xinetd
# 检查端口监听 # 检查端口监听
ss -tlnp | grep -E "631|445|515" ss -tlnp | grep -E "631|632"
``` ```
--- ---
@@ -176,14 +140,15 @@ ss -tlnp | grep -E "631|445|515"
## 八、故障排除 ## 八、故障排除
### 问题1Windows 无法连接 IPP 打印机 ### 问题1Windows 无法连接 IPP 打印机
**原因**Windows IPP 客户端强制使用 HTTPS自签名证书不受信任 **原因**常见原因是客户端缓存了旧队列、服务器 IP 变化,或没有在同一内网网段。
**解决**使用 LPR 协议或 SMB 协议代替 **解决**删除旧打印机后重新添加,使用 `http://服务器IP:631/printers/打印机名` 或 Windows 设置里的“添加打印机”重新发现。
### 问题2SMB 连接失败0x80070035 ### 问题2驱动管理器无法打开
**原因**445 端口被防火墙/ISP 阻止 **原因**驱动管理器默认只允许内网来源访问,且需要安装时生成的 `admin` 密码。
**解决** **解决**
- 检查云服务器安全组是否开放 445 端口 - 确认客户端和打印服务器在同一内网
- 局域网内通常无此问题 - 查看密码:`cat /opt/cups-driver-manager/.password`
- 查看服务状态:`systemctl status cups-driver-manager`
### 问题3打印任务卡住 ### 问题3打印任务卡住
**解决** **解决**
@@ -219,7 +184,7 @@ locale -a | grep zh_CN
## 十、待测试项目 ## 十、待测试项目
- [ ] 局域网 Windows SMB 连接 - [ ] 局域网 Windows IPP/CUPS 连接
- [ ] 局域网 macOS/iOS AirPrint 自动发现 - [ ] 局域网 macOS/iOS AirPrint 自动发现
- [ ] 局域网 Android Mopria 打印 - [ ] 局域网 Android Mopria 打印
- [ ] 真实 USB 打印机连接测试 - [ ] 真实 USB 打印机连接测试

View File

@@ -32,7 +32,7 @@ https://mirrors.aliyun.com/debian-cd/current/amd64/iso-dvd/debian-12.8.0-amd64-D
sudo dd if=debian-12.8.0-amd64-DVD-1.iso of=/dev/sdX bs=4M status=progress sudo dd if=debian-12.8.0-amd64-DVD-1.iso of=/dev/sdX bs=4M status=progress
sync sync
``` ```
注意sdX 替<EFBFBD><EFBFBD>为你的U盘设备名) 注意sdX 替为你的 U 盘设备名)
--- ---
@@ -293,7 +293,7 @@ apt update && apt upgrade -y
**方法一:使用一键脚本(推荐)** **方法一:使用一键脚本(推荐)**
```bash ```bash
apt install -y wget apt install -y wget
wget -O setup_cups.sh https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh wget -O setup_cups.sh https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups.sh
chmod +x setup_cups.sh chmod +x setup_cups.sh
./setup_cups.sh ./setup_cups.sh
``` ```

View File

@@ -10,6 +10,7 @@
- AirPrint 支持iOS/macOS 自动发现) - AirPrint 支持iOS/macOS 自动发现)
- 虚拟 PDF 打印机(测试连接用) - 虚拟 PDF 打印机(测试连接用)
- 多种打印机驱动可选 - 多种打印机驱动可选
- 驱动管理器(默认仅允许内网访问)
- 支持一键卸载 - 支持一键卸载
## 快速安装 ## 快速安装
@@ -73,6 +74,7 @@ chmod +x setup_cups.sh
|------|------|------| |------|------|------|
| CUPS | 631 | 打印服务/Web管理界面 | | CUPS | 631 | 打印服务/Web管理界面 |
| Avahi | 5353 | mDNS/AirPrint 自动发现 | | Avahi | 5353 | mDNS/AirPrint 自动发现 |
| 驱动管理器 | 632 | 内网上传安装打印机驱动(可选) |
## 常用命令 ## 常用命令
@@ -109,7 +111,7 @@ lpinfo -v | grep usb
## 常见问题 ## 常见问题
### 手机打印提示"不再接受加密的作业" ### 手机打印提示"不再接受加密的作业"
正常提示,点击"继续"即可。这是因为服务器配置为允许非加密连接 脚本现在配置为 `DefaultEncryption IfRequested`,允许 HTTP也接受客户端主动发起的 HTTPS。如仍提示通常是客户端缓存了旧队列删除后重新发现打印机即可
### 手机发送打印任务很慢 ### 手机发送打印任务很慢
脚本已配置 `HostNameLookups Off` 解决此问题。如果仍然慢,检查网络连接。 脚本已配置 `HostNameLookups Off` 解决此问题。如果仍然慢,检查网络连接。

View File

@@ -1,6 +1,6 @@
[Unit] [Unit]
Description=CUPS Printer Driver Manager Description=CUPS Printer Driver Manager
Documentation=https://gitee.com/yu-yon/S905L3A Documentation=https://git.workyai.cn/237899745/S905L3A
After=network.target cups.service After=network.target cups.service
Wants=cups.service Wants=cups.service
@@ -8,10 +8,11 @@ Wants=cups.service
Type=simple Type=simple
User=root User=root
WorkingDirectory=/opt/cups-driver-manager 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 Restart=on-failure
RestartSec=5 RestartSec=5
Environment=DRIVER_MANAGER_PASSWORD=admin Environment=DRIVER_MANAGER_PASSWORD=admin
Environment=DRIVER_MANAGER_ALLOW_PRIVATE_ONLY=1
# 安全设置 # 安全设置
NoNewPrivileges=false NoNewPrivileges=false

View File

@@ -12,6 +12,7 @@ import tempfile
import shutil import shutil
import tarfile import tarfile
import zipfile import zipfile
import ipaddress
from pathlib import Path from pathlib import Path
from functools import wraps 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_USERNAME = os.environ.get('DRIVER_MANAGER_USERNAME', 'admin')
ADMIN_PASSWORD = os.environ.get('DRIVER_MANAGER_PASSWORD', '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['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH 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) 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): def check_auth(username, password):
"""验证用户名和密码""" """验证用户名和密码"""
return username == ADMIN_USERNAME and password == ADMIN_PASSWORD return username == ADMIN_USERNAME and password == ADMIN_PASSWORD
@@ -168,7 +210,7 @@ def install_tar_gz(filepath):
try: try:
# 解压 # 解压
with tarfile.open(filepath, 'r:gz') as tar: with tarfile.open(filepath, 'r:gz') as tar:
tar.extractall(extract_dir) safe_extract_tar(tar, extract_dir)
results.append(('解压文件', { results.append(('解压文件', {
'success': True, 'success': True,
'stdout': f'已解压到 {extract_dir}', 'stdout': f'已解压到 {extract_dir}',
@@ -240,7 +282,7 @@ def install_zip(filepath):
try: try:
# 解压 # 解压
with zipfile.ZipFile(filepath, 'r') as zip_ref: with zipfile.ZipFile(filepath, 'r') as zip_ref:
zip_ref.extractall(extract_dir) safe_extract_zip(zip_ref, extract_dir)
results.append(('解压文件', { results.append(('解压文件', {
'success': True, 'success': True,
'stdout': f'已解压到 {extract_dir}', 'stdout': f'已解压到 {extract_dir}',

View File

@@ -17,12 +17,32 @@ YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# 运行时可用环境变量覆盖,默认面向内网部署。
REPO_ARCHIVE_URL="${REPO_ARCHIVE_URL:-https://git.workyai.cn/237899745/S905L3A/archive/master.zip}"
REPO_ARCHIVE_FALLBACK_URL="${REPO_ARCHIVE_FALLBACK_URL:-https://gitee.com/yu-yon/S905L3A/repository/archive/master.zip}"
CUPS_ALLOWED_NET="${CUPS_ALLOWED_NET:-@LOCAL}"
DRIVER_MANAGER_HOST="${DRIVER_MANAGER_HOST:-0.0.0.0}"
DRIVER_MANAGER_PRIVATE_ONLY="${DRIVER_MANAGER_PRIVATE_ONLY:-1}"
# 打印带颜色的信息 # 打印带颜色的信息
info() { echo -e "${BLUE}[信息]${NC} $1"; } info() { echo -e "${BLUE}[信息]${NC} $1"; }
success() { echo -e "${GREEN}[成功]${NC} $1"; } success() { echo -e "${GREEN}[成功]${NC} $1"; }
warn() { echo -e "${YELLOW}[警告]${NC} $1"; } warn() { echo -e "${YELLOW}[警告]${NC} $1"; }
error() { echo -e "${RED}[错误]${NC} $1"; exit 1; } error() { echo -e "${RED}[错误]${NC} $1"; exit 1; }
download_repo_archive() {
local output_file=$1
if wget -q --show-progress -O "$output_file" "$REPO_ARCHIVE_URL" 2>/dev/null || \
curl -fsSL -o "$output_file" "$REPO_ARCHIVE_URL" 2>/dev/null; then
return 0
fi
warn "主仓库下载失败,尝试镜像源..."
wget -q --show-progress -O "$output_file" "$REPO_ARCHIVE_FALLBACK_URL" 2>/dev/null || \
curl -fsSL -o "$output_file" "$REPO_ARCHIVE_FALLBACK_URL" 2>/dev/null
}
# 检查是否为root用户 # 检查是否为root用户
check_root() { check_root() {
if [ "$(id -u)" != "0" ]; then if [ "$(id -u)" != "0" ]; then
@@ -355,8 +375,10 @@ configure_static_ip_netplan() {
done done
dns_list=$(echo "$dns_list" | sed 's/^, //') dns_list=$(echo "$dns_list" | sed 's/^, //')
local target_file="/etc/netplan/99-cups-static-ip.yaml"
# 创建新的netplan配置 # 创建新的netplan配置
cat > /etc/netplan/01-static-ip.yaml << EOF cat > "$target_file" << EOF
# 静态 IP 配置 - 由 CUPS 一键脚本生成 # 静态 IP 配置 - 由 CUPS 一键脚本生成
network: network:
version: 2 version: 2
@@ -374,13 +396,13 @@ network:
EOF EOF
# 设置正确的权限(避免 "Permissions too open" 警告) # 设置正确的权限(避免 "Permissions too open" 警告)
chmod 600 /etc/netplan/01-static-ip.yaml chmod 600 "$target_file"
# 删除其他可能冲突的配置 # 只清理脚本旧版本生成的 netplan 文件,避免误删用户自己的网络配置
for f in /etc/netplan/*.yaml; do for f in /etc/netplan/01-static-ip.yaml /etc/netplan/01-dhcp.yaml /etc/netplan/99-cups-static-ip.yaml /etc/netplan/99-cups-dhcp.yaml; do
if [ "$f" != "/etc/netplan/01-static-ip.yaml" ] && [ -f "$f" ]; then if [ "$f" != "$target_file" ] && [ -f "$f" ]; then
rm -f "$f" rm -f "$f"
info "移除冲突配置: $f" info "移除脚本旧配置: $f"
fi fi
done done
@@ -466,7 +488,7 @@ configure_dhcp() {
echo -e "${YELLOW}警告: 切换为 DHCP 后IP 地址可能会改变!${NC}" echo -e "${YELLOW}警告: 切换为 DHCP 后IP 地址可能会改变!${NC}"
echo " 请确保你能通过其他方式(如显示器/串口)访问设备" echo " 请确保你能通过其他方式(如显示器/串口)访问设备"
echo "" echo ""
read -p "确定要切<EFBFBD><EFBFBD>为 DHCP 吗? [y/N]: " confirm < /dev/tty read -p "确定要切为 DHCP 吗? [y/N]: " confirm < /dev/tty
confirm=${confirm:-N} confirm=${confirm:-N}
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
@@ -528,8 +550,10 @@ configure_dhcp_netplan() {
fi fi
done done
local target_file="/etc/netplan/99-cups-dhcp.yaml"
# 创建新的 netplan DHCP 配置 # 创建新的 netplan DHCP 配置
cat > /etc/netplan/01-dhcp.yaml << EOF cat > "$target_file" << EOF
# DHCP 配置 - 由 CUPS 一键脚本生成 # DHCP 配置 - 由 CUPS 一键脚本生成
network: network:
version: 2 version: 2
@@ -540,13 +564,13 @@ network:
EOF EOF
# 设置正确的权限 # 设置正确的权限
chmod 600 /etc/netplan/01-dhcp.yaml chmod 600 "$target_file"
# 删除其他可能冲突的配置 # 只清理脚本旧版本生成的 netplan 文件,避免误删用户自己的网络配置
for f in /etc/netplan/*.yaml; do for f in /etc/netplan/01-static-ip.yaml /etc/netplan/01-dhcp.yaml /etc/netplan/99-cups-static-ip.yaml /etc/netplan/99-cups-dhcp.yaml; do
if [ "$f" != "/etc/netplan/01-dhcp.yaml" ] && [ -f "$f" ]; then if [ "$f" != "$target_file" ] && [ -f "$f" ]; then
rm -f "$f" rm -f "$f"
info "移除冲突配置: $f" info "移除脚本旧配置: $f"
fi fi
done done
@@ -922,15 +946,13 @@ install_chinese_templates() {
cp -f "$SCRIPT_DIR/cups-templates-zh_CN/"*.tmpl "$templates_dir/" cp -f "$SCRIPT_DIR/cups-templates-zh_CN/"*.tmpl "$templates_dir/"
success "中文界面模板安装完成(本地)" success "中文界面模板安装完成(本地)"
else else
# 从 Gitee 下载模板(使用 zip 包方式,更可靠) # 从当前仓库下载模板(使用 zip 包方式,更可靠)
info "从 Gitee 下载中文模板..." info "从仓库下载中文模板..."
local tmp_dir=$(mktemp -d) local tmp_dir=$(mktemp -d)
local zip_url="https://gitee.com/yu-yon/S905L3A/repository/archive/master.zip"
# 下载仓库 zip 包 # 下载仓库 zip 包
if wget -q --show-progress -O "$tmp_dir/repo.zip" "$zip_url" 2>/dev/null || \ if download_repo_archive "$tmp_dir/repo.zip"; then
curl -sL -o "$tmp_dir/repo.zip" "$zip_url" 2>/dev/null; then
# 解压 # 解压
cd "$tmp_dir" cd "$tmp_dir"
@@ -1012,13 +1034,11 @@ install_driver_manager() {
cp -f "$SCRIPT_DIR/cups-driver-manager/cups-driver-manager.service" /etc/systemd/system/ 2>/dev/null || true cp -f "$SCRIPT_DIR/cups-driver-manager/cups-driver-manager.service" /etc/systemd/system/ 2>/dev/null || true
info "从本地复制驱动管理器文件" info "从本地复制驱动管理器文件"
else else
# 从 Gitee 下载 # 从当前仓库下载
info "从 Gitee 下载驱动管理器..." info "从仓库下载驱动管理器..."
local tmp_dir=$(mktemp -d) local tmp_dir=$(mktemp -d)
local zip_url="https://gitee.com/yu-yon/S905L3A/repository/archive/master.zip"
if wget -q --show-progress -O "$tmp_dir/repo.zip" "$zip_url" 2>/dev/null || \ if download_repo_archive "$tmp_dir/repo.zip"; then
curl -sL -o "$tmp_dir/repo.zip" "$zip_url" 2>/dev/null; then
cd "$tmp_dir" cd "$tmp_dir"
unzip -q repo.zip 2>/dev/null unzip -q repo.zip 2>/dev/null
@@ -1043,7 +1063,13 @@ install_driver_manager() {
# 更新 systemd 服务文件中的密码 # 更新 systemd 服务文件中的密码
if [ -f /etc/systemd/system/cups-driver-manager.service ]; then if [ -f /etc/systemd/system/cups-driver-manager.service ]; then
sed -i "s/DRIVER_MANAGER_PASSWORD=admin/DRIVER_MANAGER_PASSWORD=$admin_pass/" /etc/systemd/system/cups-driver-manager.service sed -i "s/DRIVER_MANAGER_PASSWORD=.*/DRIVER_MANAGER_PASSWORD=$admin_pass/" /etc/systemd/system/cups-driver-manager.service
sed -i "s#^ExecStart=.*#ExecStart=/usr/bin/python3 $install_dir/driver_manager.py --host $DRIVER_MANAGER_HOST --port 632#" /etc/systemd/system/cups-driver-manager.service
if grep -q "DRIVER_MANAGER_ALLOW_PRIVATE_ONLY" /etc/systemd/system/cups-driver-manager.service; then
sed -i "s/DRIVER_MANAGER_ALLOW_PRIVATE_ONLY=.*/DRIVER_MANAGER_ALLOW_PRIVATE_ONLY=$DRIVER_MANAGER_PRIVATE_ONLY/" /etc/systemd/system/cups-driver-manager.service
else
sed -i "/DRIVER_MANAGER_PASSWORD=/a Environment=DRIVER_MANAGER_ALLOW_PRIVATE_ONLY=$DRIVER_MANAGER_PRIVATE_ONLY" /etc/systemd/system/cups-driver-manager.service
fi
else else
# 手动创建服务文件 # 手动创建服务文件
cat > /etc/systemd/system/cups-driver-manager.service << EOF cat > /etc/systemd/system/cups-driver-manager.service << EOF
@@ -1056,10 +1082,11 @@ Wants=cups.service
Type=simple Type=simple
User=root User=root
WorkingDirectory=$install_dir WorkingDirectory=$install_dir
ExecStart=/usr/bin/python3 $install_dir/driver_manager.py --port 632 ExecStart=/usr/bin/python3 $install_dir/driver_manager.py --host $DRIVER_MANAGER_HOST --port 632
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5
Environment=DRIVER_MANAGER_PASSWORD=$admin_pass Environment=DRIVER_MANAGER_PASSWORD=$admin_pass
Environment=DRIVER_MANAGER_ALLOW_PRIVATE_ONLY=$DRIVER_MANAGER_PRIVATE_ONLY
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
@@ -1147,6 +1174,8 @@ install_pdf_printer() {
# 配置CUPS # 配置CUPS
configure_cups() { configure_cups() {
info "配置 CUPS 允许远程访问..." info "配置 CUPS 允许远程访问..."
local cups_allow="${CUPS_ALLOWED_NET:-@LOCAL}"
info "CUPS 访问范围: ${cups_allow}"
# 备份原配置 # 备份原配置
cp /etc/cups/cupsd.conf /etc/cups/cupsd.conf.bak cp /etc/cups/cupsd.conf /etc/cups/cupsd.conf.bak
@@ -1165,9 +1194,11 @@ configure_cups() {
sed -i '/^Listen.*631/a ServerAlias *' /etc/cups/cupsd.conf sed -i '/^Listen.*631/a ServerAlias *' /etc/cups/cupsd.conf
fi fi
# 禁用强制加密(允许 HTTP 访问) # 内网场景允许 HTTP同时不拒绝客户端主动发起的 HTTPS。
if ! grep -q "^DefaultEncryption" /etc/cups/cupsd.conf; then if ! grep -q "^DefaultEncryption" /etc/cups/cupsd.conf; then
sed -i '/^ServerAlias/a DefaultEncryption Never' /etc/cups/cupsd.conf sed -i '/^ServerAlias/a DefaultEncryption IfRequested' /etc/cups/cupsd.conf
else
sed -i 's/^DefaultEncryption.*/DefaultEncryption IfRequested/' /etc/cups/cupsd.conf
fi fi
# 启用网络浏览 # 启用网络浏览
@@ -1184,43 +1215,46 @@ configure_cups() {
# 修改 Policy default 允许匿名打印 # 修改 Policy default 允许匿名打印
# 找到 <Limit Create-Job Print-Job Print-URI Validate-Job> 块并修改 # 找到 <Limit Create-Job Print-Job Print-URI Validate-Job> 块并修改
sed -i '/<Limit Create-Job Print-Job Print-URI Validate-Job>/,/<\/Limit>/{ sed -i "/<Limit Create-Job Print-Job Print-URI Validate-Job>/,/<\/Limit>/{
s/Order deny,allow/Order allow,deny/ s/Order deny,allow/Order allow,deny/
/Require user/d /Require user/d
/Order/a\ Allow all /Allow /d
}' /etc/cups/cupsd.conf /Order/a\\ Allow ${cups_allow}
}" /etc/cups/cupsd.conf
# 配置访问权限 - 允许所有网络访问 # 配置访问权限 - 默认仅允许本机和本地网络访问
# 先删除现有的 Location 块,然后重新添加 # 先删除现有的 Location 块,然后重新添加
cat > /tmp/cups_locations.conf << 'EOF' cat > /tmp/cups_locations.conf << EOF
# 允许所有网络访问(内网环境使用) # 允许本机和本地网络访问(内网环境使用)
<Location /> <Location />
Order allow,deny Order allow,deny
Allow all Allow ${cups_allow}
</Location> </Location>
<Location /admin> <Location /admin>
AuthType Default
Require user @SYSTEM
Order allow,deny Order allow,deny
Allow all Allow ${cups_allow}
</Location> </Location>
<Location /admin/conf> <Location /admin/conf>
AuthType Default AuthType Default
Require user @SYSTEM Require user @SYSTEM
Order allow,deny Order allow,deny
Allow all Allow ${cups_allow}
</Location> </Location>
# 允许远程打印 # 允许远程打印
<Location /printers> <Location /printers>
Order allow,deny Order allow,deny
Allow all Allow ${cups_allow}
</Location> </Location>
<Location /printers/*> <Location /printers/*>
Order allow,deny Order allow,deny
Allow all Allow ${cups_allow}
</Location> </Location>
EOF EOF
@@ -1267,7 +1301,7 @@ main() {
# 询问是否安装驱动管理器 # 询问是否安装驱动管理器
echo -e "${YELLOW}是否安装驱动管理器Web界面安装打印机驱动${NC}" echo -e "${YELLOW}是否安装驱动管理器Web界面安装打印机驱动${NC}"
echo " 推荐:选择 Y可通过网页上传安装 .deb/.ppd/.tar.gz 等驱动" echo " 推荐:选择 Y可通过网页上传安装 .deb/.ppd/.tar.gz 等驱动"
echo " 端口: 632" echo " 端口: 632(默认仅允许内网来源访问)"
echo "" echo ""
read -p "安装驱动管理器? [Y/n]: " install_dm < /dev/tty read -p "安装驱动管理器? [Y/n]: " install_dm < /dev/tty
install_dm=${install_dm:-Y} install_dm=${install_dm:-Y}
@@ -1419,7 +1453,7 @@ main() {
echo -e " ${GREEN}${NC} 地址: http://${LOCAL_IP}:632 ${GREEN}${NC}" echo -e " ${GREEN}${NC} 地址: http://${LOCAL_IP}:632 ${GREEN}${NC}"
echo -e " ${GREEN}${NC} ${RED}用户名: admin${NC} ${GREEN}${NC}" echo -e " ${GREEN}${NC} ${RED}用户名: admin${NC} ${GREEN}${NC}"
echo -e " ${GREEN}${NC} ${RED}密码: ${dm_pass}${NC} ${GREEN}${NC}" echo -e " ${GREEN}${NC} ${RED}密码: ${dm_pass}${NC} ${GREEN}${NC}"
echo -e " ${GREEN}${NC} ${YELLOW}(注意不是SSH密码!)${NC} ${GREEN}${NC}" echo -e " ${GREEN}${NC} ${YELLOW}(注意不是SSH密码,仅允许内网访问)${NC} ${GREEN}${NC}"
echo -e " ${GREEN}└─────────────────────────────────────────────────────┘${NC}" echo -e " ${GREEN}└─────────────────────────────────────────────────────┘${NC}"
echo "" echo ""
fi fi
@@ -1646,7 +1680,7 @@ share_all_printers() {
echo "" echo ""
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo -e "${YELLOW} 一键共享所有打印机 ${NC}" echo -e "${YELLOW} 一键共享所有打印机 ${NC}"
echo -e "${YELLOW}══<EFBFBD><EFBFBD><EFBFBD>════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}══════════════════════════════════════════════════════════${NC}"
echo "" echo ""
# 检查CUPS是否运行 # 检查CUPS是否运行

View File

@@ -207,13 +207,13 @@ sysctl -p
```bash ```bash
# 方式一:直接运行(最简单) # 方式一:直接运行(最简单)
curl -fsSL https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh | bash curl -fsSL https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups.sh | bash
# 方式二使用wget # 方式二使用wget
wget -qO- https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh | bash wget -qO- https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups.sh | bash
# 方式三:先下载再执行(更安全) # 方式三:先下载再执行(更安全)
curl -fsSL https://gitee.com/yu-yon/S905L3A/raw/master/setup_cups.sh -o setup_cups.sh && chmod +x setup_cups.sh && ./setup_cups.sh curl -fsSL https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups.sh -o setup_cups.sh && chmod +x setup_cups.sh && ./setup_cups.sh
``` ```
脚本功能: 脚本功能:
@@ -261,7 +261,7 @@ nano /etc/cups/cupsd.conf
修改以下内容: 修改以下内容:
```conf ```conf
# 修改监听地址(允许所有IP访问) # 修改监听地址(允许本机网络访问)
Listen 0.0.0.0:631 Listen 0.0.0.0:631
Listen /run/cups/cups.sock Listen /run/cups/cups.sock
@@ -269,26 +269,28 @@ Listen /run/cups/cups.sock
Browsing Yes Browsing Yes
BrowseLocalProtocols dnssd BrowseLocalProtocols dnssd
# 修改访问权限(允许所有网络) # 修改访问权限(允许本机和本地网络)
<Location /> <Location />
Order allow,deny Order allow,deny
Allow all Allow @LOCAL
</Location> </Location>
<Location /admin> <Location /admin>
AuthType Default
Require user @SYSTEM
Order allow,deny Order allow,deny
Allow all Allow @LOCAL
</Location> </Location>
<Location /admin/conf> <Location /admin/conf>
AuthType Default AuthType Default
Require user @SYSTEM Require user @SYSTEM
Order allow,deny Order allow,deny
Allow all Allow @LOCAL
</Location> </Location>
``` ```
> **说明**: 内网环境无公网IP可直接使用 `Allow all`。如需限制访问,可改为 `Allow from 192.168.*.*` 等 > **说明**: `Allow @LOCAL` 适合内网共享,会拒绝非本地网络来源。不要把 CUPS 端口直接暴露到公网
### 4.4 将用户添加到打印组 ### 4.4 将用户添加到打印组