fix: harden intranet CUPS setup
This commit is contained in:
@@ -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"
|
|||||||
## 八、故障排除
|
## 八、故障排除
|
||||||
|
|
||||||
### 问题1:Windows 无法连接 IPP 打印机
|
### 问题1:Windows 无法连接 IPP 打印机
|
||||||
**原因**:Windows IPP 客户端强制使用 HTTPS,自签名证书不受信任
|
**原因**:常见原因是客户端缓存了旧队列、服务器 IP 变化,或没有在同一内网网段。
|
||||||
**解决**:使用 LPR 协议或 SMB 协议代替
|
**解决**:删除旧打印机后重新添加,使用 `http://服务器IP:631/printers/打印机名` 或 Windows 设置里的“添加打印机”重新发现。
|
||||||
|
|
||||||
### 问题2:SMB 连接失败(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 打印机连接测试
|
||||||
|
|||||||
@@ -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
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -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` 解决此问题。如果仍然慢,检查网络连接。
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}',
|
||||||
|
|||||||
116
setup_cups.sh
116
setup_cups.sh
@@ -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是否运行
|
||||||
|
|||||||
20
刷机教程.md
20
刷机教程.md
@@ -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 将用户添加到打印组
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user