强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

CUPS 打印服务完全指南 / 第 7 章:打印共享与发现

第 7 章:打印共享与发现

打印共享是企业环境中的核心需求。本章将详细介绍 CUPS 的打印机发现机制、共享配置以及跨网络打印方案。


7.1 打印机发现机制概览

7.1.1 发现协议对比

协议全称版本支持说明
DNS-SDDNS Service DiscoveryCUPS 1.2+推荐,基于 mDNS/Bonjour
BrowseCUPS Browse ProtocolCUPS 1.0-1.5已废弃,仅 CUPS 1.x
LDAPLightweight Directory Access ProtocolCUPS 1.2+企业目录集成
SLPService Location ProtocolCUPS 1.1+较少使用
cups-browsedcups-browsed 服务CUPS 2.x+自动发现远程打印机

7.1.2 发现协议演进

CUPS 1.0 (1999): Browse 协议 (UDP 广播)
    │
CUPS 1.2 (2006): 添加 DNS-SD 支持
    │
CUPS 1.6 (2012): Browse 协议被废弃,推荐 DNS-SD
    │
CUPS 2.x (2015+): cups-browsed + DNS-SD
    │
CUPS 3.x (2024+): 完全基于 DNS-SD/IPP Everywhere

7.2 DNS-SD (DNS Service Discovery)

7.2.1 DNS-SD 概述

DNS-SD 使用 mDNS(多播 DNS)在本地网络中发现服务:

┌─────────────────────────────────────────────────┐
│                 mDNS 工作原理                     │
│                                                 │
│  打印机发布服务:                                  │
│  HP-LaserJet._ipp._tcp.local. → 192.168.1.100  │
│                                                 │
│  客户端查询服务:                                  │
│  _ipp._tcp.local.? → 发现所有 IPP 打印机        │
│                                                 │
│  多播地址: 224.0.0.251 (IPv4)                   │
│  端口: 5353 (UDP)                               │
└─────────────────────────────────────────────────┘

7.2.2 使用 avahi-daemon

# 安装 Avahi
sudo apt install -y avahi-daemon avahi-utils

# 启动 Avahi 服务
sudo systemctl start avahi-daemon
sudo systemctl enable avahi-daemon

# 查看 Avahi 状态
sudo systemctl status avahi-daemon

7.2.3 使用 avahi-browse 发现打印机

# 发现所有 IPP 服务
avahi-browse -t -r _ipp._tcp

# 输出示例:
# + eth0 IPv4 HP LaserJet Pro M404 @ server1 Internet Printer local
# = eth0 IPv4 HP LaserJet Pro M404 @ server1 Internet Printer local
#    hostname = [HP-LaserJet.local]
#    address = [192.168.1.100]
#    port = [631]
#    txt = ["rp=ipp/print" "ty=HP LaserJet Pro M404" "pdl=application/pdf"]

# 发现特定打印机
avahi-browse -t -r _ipp._tcp | grep "LaserJet"

# 静默模式(只输出结果)
avahi-browse -t -r -p _ipp._tcp

# 发现 HTTP 服务(Web 管理界面)
avahi-browse -t -r _http._tcp

# 发现所有服务类型
avahi-browse -t -a

7.2.4 使用 avahi-publish 发布服务

# 手动发布 IPP 服务
avahi-publish -s "My Printer" _ipp._tcp 631 \
  "rp=ipp/print" "ty=My Printer" &

# 发布带子类型的服务
avahi-publish -s "My Printer" _ipp._tcp 631 \
  --subtype=_universal._sub._ipp._tcp \
  "rp=ipp/print" &

# 发布 AirPrint 服务
avahi-publish -s "AirPrint Printer" _ipp._tcp 631 \
  --subtype=_universal._sub._ipp._tcp \
  "rp=ipp/print" "txtvers=1" "URF=DM3" \
  "pdl=application/pdf,image/jpeg" "Color=T" "Duplex=T" &

7.2.5 使用 avahi-resolve 解析

# 解析主机名
avahi-resolve -n HP-LaserJet.local
# 输出: HP-LaserJet.local 192.168.1.100

# 解析服务
avahi-resolve -n _ipp._tcp.local

# 反向解析
avahi-resolve -a 192.168.1.100

7.3 Avahi 配置

7.3.1 Avahi 配置文件

# 主配置文件
cat /etc/avahi/avahi-daemon.conf

配置示例

[server]
# 主机名(默认使用系统主机名)
# host-name=printserver

# 使用 IPv4
use-ipv4=yes

# 使用 IPv6
use-ipv6=yes

# 允许点对点接口
allow-point-to-point=yes

[wide-area]
# 启用广域 DNS-SD
enable-wide-area=yes

[publish]
# 发布工作站
publish-workstation=no

# 发布打印机(重要!)
publish-printers=yes

# 发布 DNS 服务器
publish-dns-servers=

# 发布地址
publish-addresses=yes

# 发布 HINFO
publish-hinfo=yes

[reflector]
# 启用反射器(跨子网)
enable-reflector=no

[rlimits]
# 资源限制
rlimit-nproc=3
rlimit-nofile=768

7.3.2 配置 Avahi 发布 CUPS 打印机

# 方法 1: CUPS 自动发布(推荐)
# 确保 cups-browsed 已安装并运行
sudo apt install -y cups-browsed
sudo systemctl enable cups-browsed
sudo systemctl start cups-browsed

# 方法 2: 手动创建服务文件
# /etc/avahi/services/ 目录下创建 .service 文件

# 为每个打印机创建服务文件
for printer in $(lpstat -p | awk '{print $2}'); do
    sudo tee /etc/avahi/services/airprint-${printer}.service << EOF
<?xml version="1.0" standalone="no"?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
  <name replace-wildcards="yes">${printer} on %h</name>
  <service>
    <type>_ipp._tcp</type>
    <subtype>_universal._sub._ipp._tcp</subtype>
    <port>631</port>
    <txt-record>rp=ipp/print</txt-record>
    <txt-record>txtvers=1</txt-record>
    <txt-record>qtotal=1</txt-record>
    <txt-record>Transparent=T</txt-record>
    <txt-record>URF=DM3</txt-record>
  </service>
</service-group>
EOF
done

# 重启 Avahi
sudo systemctl restart avahi-daemon

7.3.3 Avahi 服务文件详解

<?xml version="1.0" standalone="no"?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
  <!-- 服务名称,%h 会被替换为主机名 -->
  <name replace-wildcards="yes">My Printer on %h</name>
  
  <service>
    <!-- 服务类型 -->
    <type>_ipp._tcp</type>
    
    <!-- 子类型(AirPrint 需要) -->
    <subtype>_universal._sub._ipp._tcp</subtype>
    
    <!-- 服务端口 -->
    <port>631</port>
    
    <!-- TXT 记录 -->
    <txt-record>rp=ipp/print</txt-record>          <!-- 资源路径 -->
    <txt-record>txtvers=1</txt-record>             <!-- TXT 版本 -->
    <txt-record>qtotal=1</txt-record>              <!-- 队列总数 -->
    <txt-record>Transparent=T</txt-record>         <!-- 透明打印 -->
    <txt-record>URF=DM3</txt-record>              <!-- Apple Raster 标签 -->
    <txt-record>kind=document,envelope</txt-record> <!-- 支持的介质类型 -->
    <txt-record>product=(CUPS Printer)</txt-record> <!-- 产品名称 -->
    <txt-record>pdl=application/pdf,image/jpeg</txt-record> <!-- 支持的格式 -->
    <txt-record>Color=T</txt-record>               <!-- 支持彩色 -->
    <txt-record>Duplex=T</txt-record>              <!-- 支持双面 -->
  </service>
</service-group>

7.4 cups-browsed

7.4.1 cups-browsed 概述

cups-browsed 是 CUPS 的自动打印机发现服务:

功能说明
自动发现通过 DNS-SD 发现网络打印机
自动添加将发现的打印机自动添加到本地 CUPS
负载均衡支持打印机组负载均衡
高可用性自动切换到可用的打印机

7.4.2 cups-browsed 配置

# 安装 cups-browsed
sudo apt install -y cups-browsed

# 配置文件
sudo vim /etc/cups/cups-browsed.conf

配置示例

# 自动发现本地网络打印机
BrowsePoll cups-server.local:631

# 指定远程 CUPS 服务器
BrowsePoll 192.168.1.100
BrowsePoll cups2.example.com

# 只发现特定类型的打印机
BrowseProtocols dnssd

# 创建本地队列(默认:是)
CreateIPPPrinterQueues Yes

# 保留队列(默认:是)
# 设置为 No 可在打印机离线时自动删除队列
AutoShutdownOnIdle No

# 日志级别
LogLevel info

# 只发现特定域
BrowseRemoteDNSSDSubTypes _universal

# 忽略特定打印机
IgnorePrinters regex1,regex2

# 自动删除离线打印机
# (秒数,0 表示禁用)
RemoteTimeout 300

7.4.3 cups-browsed 管理

# 启动 cups-browsed
sudo systemctl start cups-browsed

# 设置开机自启
sudo systemctl enable cups-browsed

# 查看状态
sudo systemctl status cups-browsed

# 重启服务
sudo systemctl restart cups-browsed

# 查看日志
journalctl -u cups-browsed -f

# 查看发现的打印机
lpstat -p

# 查看 cups-browsed 创建的队列
lpstat -v | grep "cups-browsed"

7.4.4 cups-browsed 高级配置

# /etc/cups/cups-browsed.conf

# 负载均衡配置
LoadBalancing on
# 可选值:
# on       - 在队列中的所有打印机间负载均衡
# QueueOnRemotePrinters - 远程队列负载均衡
# QueueBySubsystem - 按子系统负载均衡
# None     - 不负载均衡

# 创建 IPP Everywhere 打印机
CreateIPPPrinterQueues Yes

# 使用 IPP 优先
IPPPrinterQueueType Auto

# 只发现特定制造商
BrowseFilter manufacturer "HP"

# 排除特定打印机
BrowseFilter reject "Old Printer"

# 配置默认选项
# DefaultOption media A4
# DefaultOption sides two-sided-long-edge

# 自动删除空闲打印机
AutoShutdownTimeout 60

# 保留时间(秒)
RemoteTimeout 600

7.5 Browse 协议(已废弃)

注意:Browse 协议已在 CUPS 1.6 中被废弃,仅在旧版本中使用。

7.5.1 Browse 协议工作原理

┌──────────────┐  UDP 广播  ┌──────────────┐
│ CUPS 服务器 A │ ─────────▶│ CUPS 服务器 B │
│  (发布者)     │  端口 631  │  (订阅者)    │
└──────────────┘           └──────────────┘
       │                          │
       │                          │
       ▼                          ▼
   打印机列表                  打印机列表
   (本地+远程)                 (本地+远程)

7.5.2 Browse 协议配置(旧版本)

# CUPS 1.5 及更早版本配置

# /etc/cups/cupsd.conf

# 启用 Browse(发布打印机)
BrowseAddress @LOCAL
# 或指定地址
# BrowseAddress 192.168.1.255

# 接收 Browse(发现打印机)
BrowseAllow all
# 或指定网络
# BrowseAllow 192.168.1.0/24

# 设置 Browse 协议
BrowseProtocols cups
# 或使用 LDAP
# BrowseProtocols ldap

# 设置 Browse 超时
BrowseTimeout 300

7.6 跨网络打印共享

7.6.1 多子网打印架构

┌─────────────────────────────────────────────────┐
│  子网 A (192.168.1.0/24)                        │
│  ┌─────────┐     ┌─────────┐                   │
│  │ 工作站1  │     │ 工作站2  │                   │
│  └────┬────┘     └────┬────┘                   │
│       │               │                         │
│       └───────┬───────┘                         │
│               │                                 │
│        ┌──────▼──────┐                          │
│        │ CUPS 服务器 A│                          │
│        │  (主)       │                          │
│        └──────┬──────┘                          │
└───────────────┼─────────────────────────────────┘
                │
        ┌───────┴───────┐
        │   路由器/防火墙 │
        └───────┬───────┘
                │
┌───────────────┼─────────────────────────────────┐
│  子网 B (192.168.2.0/24)                        │
│               │                                 │
│        ┌──────▼──────┐                          │
│        │ CUPS 服务器 B│                          │
│        │  (备份)     │                          │
│        └──────┬──────┘                          │
│       ┌───────┴───────┐                         │
│       │               │                         │
│  ┌────▼────┐    ┌────▼────┐                    │
│  │ 工作站3  │    │ 工作站4  │                    │
│  └─────────┘    └─────────┘                    │
└─────────────────────────────────────────────────┘

7.6.2 跨子网配置

# 方法 1: 使用 cups-browsed 跨子网
# 在子网 B 的 cups-browsed 中配置
# /etc/cups/cups-browsed.conf
BrowsePoll 192.168.1.100:631

# 方法 2: 使用 Avahi 反射器
# 在路由器上启用 Avahi 反射器
# /etc/avahi/avahi-daemon.conf
[reflector]
enable-reflector=yes

# 方法 3: 使用 VPN
# 配置 OpenVPN 或 WireGuard 隧道
# 打印机流量通过 VPN 传输

# 方法 4: 使用 DNS 转发
# 配置 DNS 服务器转发 mDNS 查询

7.6.3 使用 Avahi 反射器

# 在连接两个子网的主机上配置
sudo vim /etc/avahi/avahi-daemon.conf

[reflector]
enable-reflector=yes
reflect-ipv=no

# 重启 Avahi
sudo systemctl restart avahi-daemon

# 验证跨子网发现
# 在子网 B 的主机上运行
avahi-browse -t -r _ipp._tcp
# 应该能看到子网 A 的打印机

7.6.4 使用 OpenVPN 隧道

# 服务器端 (192.168.1.100)
# /etc/openvpn/server.conf
server 10.8.0.0 255.255.255.0
push "route 192.168.1.0 255.255.255.0"

# 客户端
# /etc/openvpn/client.conf
remote vpn.example.com 1194

# 客户端添加打印机
sudo lpadmin -p VPNPrinter -E \
  -v "ipp://192.168.1.100/printers/myprinter" \
  -m "everywhere"

7.7 访问控制

7.7.1 CUPS 访问控制层级

┌─────────────────────────────────────────────────┐
│              CUPS 访问控制模型                    │
│                                                 │
│  1. IP 地址过滤                                  │
│     Allow/Deny IP 地址范围                       │
│                                                 │
│  2. 用户认证                                     │
│     Basic/Digest/证书认证                        │
│                                                 │
│  3. 操作权限                                     │
│     Read/Write/Admin 权限                        │
│                                                 │
│  4. 打印机级别                                   │
│     每个打印机独立的访问控制                      │
└─────────────────────────────────────────────────┘

7.7.2 IP 地址过滤

# /etc/cups/cupsd.conf

# 允许本地访问
<Location />
  Order allow,deny
  Allow localhost
  Allow 127.0.0.1
  Allow @LOCAL
</Location>

# 允许特定网络
<Location /printers>
  Order allow,deny
  Allow localhost
  Allow 192.168.1.0/24
  Allow 10.0.0.0/8
</Location>

# 允许特定 IP
<Location /admin>
  Order allow,deny
  Allow localhost
  Allow 192.168.1.100
  Allow 192.168.1.101
</Location>

# 拒绝特定 IP
<Location />
  Order deny,allow
  Deny 192.168.1.50
  Allow all
</Location>

7.7.3 用户认证配置

# /etc/cups/cupsd.conf

# 基本认证
DefaultAuthType Basic

# 摘要认证(更安全)
DefaultAuthType Digest

# 本地认证(使用系统用户)
AuthType Default

# 管理界面认证
<Location /admin>
  AuthType Default
  Require user @SYSTEM
</Location>

# 配置文件认证
<Location /admin/conf>
  AuthType Default
  Require user @SYSTEM
</Location>

# 打印机级别认证
<Printer secret-printer>
  AuthType Default
  Require user john mary bob
</Printer>

# 组认证
<Printer finance-printer>
  AuthType Default
  Require group finance
</Printer>

7.7.4 创建 CUPS 用户

# 添加用户到 lpadmin 组(管理权限)
sudo usermod -aG lpadmin username

# 创建 CUPS 特定用户(使用 htdigest)
sudo htdigest /etc/cups/passwd "CUPS" username

# 或使用 Samba 用户
# 需要配置 PAM

# 查看 CUPS 用户
cat /etc/cups/passwd

# 删除 CUPS 用户
sudo htdigest /etc/cups/passwd "CUPS" username

7.7.5 打印机级别的访问控制

# 为特定打印机设置访问控制
sudo lpadmin -p myprinter \
  -u allow:john,mary,bob \
  -u deny:guest

# 允许所有用户
sudo lpadmin -p myprinter -u allow:all

# 只允许特定组
sudo lpadmin -p myprinter -u allow:@finance

# 拒绝所有用户(禁用打印机)
sudo lpadmin -p myprinter -u deny:all

# 查看打印机访问控制
lpstat -p myprinter -l

7.8 Samba 打印共享

7.8.1 安装 Samba

# 安装 Samba
sudo apt install -y samba samba-common

# 配置 Samba
sudo vim /etc/samba/smb.conf

7.8.2 配置 Samba 共享打印机

# /etc/samba/smb.conf

[global]
   workgroup = WORKGROUP
   server string = Print Server
   security = user
   map to guest = bad user
   
   # 打印机配置
   printing = cups
   printcap name = cups
   load printers = yes
   cups server = localhost

[printers]
   comment = All Printers
   path = /var/spool/samba
   browseable = no
   guest ok = no
   writable = no
   printable = yes
   create mask = 0700

[print$]
   comment = Printer Drivers
   path = /var/lib/samba/printers
   browseable = yes
   read only = yes
   guest ok = no
# 创建 Samba 打印机共享
sudo mkdir -p /var/spool/samba
sudo chmod 1777 /var/spool/samba

# 创建驱动目录
sudo mkdir -p /var/lib/samba/printers
sudo chmod 755 /var/lib/samba/printers

# 添加 Samba 用户
sudo smbpasswd -a username

# 重启 Samba
sudo systemctl restart smbd nmbd

7.8.3 Windows 客户端连接

# Windows 连接到 Samba 共享打印机
# 方法 1: 资源管理器
\\linux-server\printer-name

# 方法 2: 添加打印机向导
# 设置 → 设备 → 打印机和扫描仪 → 添加打印机
# 选择 "按名称选择共享打印机"
# 输入: \\linux-server\printer-name

# 方法 3: 命令行
rundll32 printui.dll,PrintUIEntry /in /n \\linux-server\printer-name

7.9 LDAP 集成

7.9.1 CUPS LDAP 配置

# 安装 LDAP 支持
sudo apt install -y libnss-ldap libpam-ldap

# 配置 CUPS 使用 LDAP
# /etc/cups/cupsd.conf

# LDAP 认证
AuthType Default
AuthLDAPURL ldap://ldap.example.com/ou=people,dc=example,dc=example?uid

# LDAP 组认证
AuthLDAPGroupAttribute memberUid
AuthLDAPGroupAttributeIsDN off

# 使用 LDAP 进行打印机发现
# BrowseProtocols ldap
# BrowseLDAPServer ldap.example.com
# BrowseLDAPBase ou=printers,dc=example,dc=com

7.9.2 LDAP 打印机条目示例

# 打印机 LDAP 条目
dn: cn=HP-LaserJet,ou=printers,dc=example,dc=com
objectClass: printer
objectClass: top
cn: HP-LaserJet
printer-uri: ipp://192.168.1.100/ipp/print
printer-location: 3rd Floor
printer-make-and-model: HP LaserJet Pro M404
printer-type: 8425492

7.10 业务场景

7.10.1 场景一:办公室打印共享

# 需求:为 50 人办公室配置集中打印

# 步骤 1: 配置 CUPS 服务器
sudo cupsctl --share-printers
sudo cupsctl BrowseLocalProtocols=dnssd

# 步骤 2: 配置防火墙
sudo ufw allow 631/tcp
sudo ufw allow 5353/udp

# 步骤 3: 安装 cups-browsed
sudo apt install -y cups-browsed
sudo systemctl enable cups-browsed

# 步骤 4: 客户端自动发现
# 客户端只需要安装 cups-browsed
# 打印机将自动出现在打印机列表中

7.10.2 场景二:多部门打印隔离

# 需求:不同部门只能访问自己的打印机

# 配置部门打印机
sudo lpadmin -p Finance-Printer -E \
  -v socket://192.168.1.100:9100 \
  -u allow:@finance

sudo lpadmin -p HR-Printer -E \
  -v socket://192.168.1.101:9100 \
  -u allow:@hr

sudo lpadmin -p IT-Printer -E \
  -v socket://192.168.1.102:9100 \
  -u allow:@it

# 创建部门共享打印机(所有部门可用)
sudo lpadmin -p Shared-Printer -E \
  -v socket://192.168.1.103:9100 \
  -u allow:all

7.10.3 场景三:跨站点打印

# 需求:北京和上海办公室共享打印服务

# 北京 CUPS 服务器配置
# /etc/cups/cups-browsed.conf
BrowsePoll cups-shanghai.example.com:631

# 上海 CUPS 服务器配置
# /etc/cups/cups-browsed.conf
BrowsePoll cups-beijing.example.com:631

# 客户端配置(两个站点)
# /etc/cups/cups-browsed.conf
BrowsePoll cups-local.example.com:631
BrowseRemoteProtocols cups

7.11 扩展阅读

资源链接
Avahi 项目https://avahi.org/
DNS-SD 规范https://datatracker.ietf.org/doc/html/rfc6763
mDNS 规范https://datatracker.ietf.org/doc/html/rfc6762
cups-browsed 手册man cups-browsed
Samba 文档https://www.samba.org/samba/docs/
CUPS 共享文档https://www.cups.org/doc/sharing.html

7.12 本章小结

主题关键要点
DNS-SD基于 mDNS 的服务发现,推荐使用
AvahiLinux 的 mDNS/Bonjour 实现
cups-browsed自动发现和添加远程打印机
Browse 协议已废弃,仅用于旧版 CUPS
跨网络使用 Avahi 反射器、VPN 或 DNS 转发
访问控制IP 过滤、用户认证、打印机级别权限

下一章预告:我们将深入学习 CUPS 的过滤器和后端系统,包括 MIME 类型检测、文档转换和自定义过滤器开发。


7.13 练习题

  1. 发现题:使用 avahi-browse 发现网络中的所有 IPP 打印机,并记录其 URI。

  2. 共享题:配置 CUPS 共享打印机,使同一子网内的其他计算机可以自动发现并使用。

  3. 安全题:为打印机配置访问控制,只允许特定用户组打印。

  4. 跨网络题:配置 Avahi 反射器,实现两个子网之间的打印机发现。

  5. Samba 题:配置 Samba 共享打印机,使 Windows 客户端可以连接使用。