# 16.7 Samba 文件共享

## Samba 概述

Samba 是对服务器消息块/通用 Internet 文件系统（Server Message Block/Common Internet File System，SMB/CIFS）协议的自由软件重新实现。CIFS 是 SMB 的衍生协议，为跨平台文件与打印服务提供标准接口。其核心目标是实现 Unix 系统与 Windows 网络环境的互操作性。

从技术架构上看，Samba 通过 smbd（文件与打印服务守护进程）和 nmbd（NetBIOS 名称服务守护进程）两个核心组件协同工作，实现与 Windows 网络环境的无缝集成。smbd 负责处理文件共享与打印服务请求，nmbd 提供 NetBIOS 名称解析与网络浏览功能。

Samba 需要在防火墙上开放 TCP 端口 139（NetBIOS 会话服务）、445（SMB over TCP）和 UDP 端口 137（NetBIOS 名称服务）、138（NetBIOS 数据报服务）。这些端口是 SMB/CIFS 协议正常工作所必需的网络通信端口。

“Samba”一词在葡萄牙语和英语中也指“桑巴舞”，具有热情奔放的含义。

## 软件安装

本节介绍如何安装 Samba，有两种主要安装方式可供选择。

* 使用 pkg 安装：

```sh
# pkg install samba420
```

* 或使用 Ports 安装：

```sh
# cd /usr/ports/net/samba420/ 
# make install clean
```

## 安装后信息

```sh
# pkg info -D samba420
samba420-4.20.7_4:
On install:  # 安装提示：
How to start: http://wiki.samba.org/index.php/Samba4/HOWTO  
如何启动：参见官方指南

* Your configuration is: /usr/local/etc/smb4.conf
* 你的配置文件路径是：/usr/local/etc/smb4.conf

* All the relevant databases are under: /var/db/samba4
* 所有相关数据库位于：/var/db/samba4

* All the logs are under: /var/log/samba4
* 所有日志位于：/var/log/samba4

* Provisioning script is: /usr/local/bin/samba-tool
* # 初始化脚本路径为：/usr/local/bin/samba-tool

For the working DNS updates you will need to either build dns/bind9* 
# 若要正常使用 DNS 更新功能，需要：
with the enabled GSSAPI(GSSAPI_MIT5 is recommended) or install        
# 要么构建启用了 GSSAPI（推荐 GSSAPI_MIT5）的 dns/bind9*，
dns/samba-nsupdate package, which is preconfigured with such a support. 
# 要么安装 dns/samba-nsupdate 包，它已预配置了所需支持。

You will need to specify location of the 'nsupdate' command in the    
smb4.conf file:
# 你需要在 smb4.conf 中指定 nsupdate 命令的位置：

    nsupdate command = /usr/local/bin/samba-nsupdate -g  # 示例配置

For additional documentation check: https://wiki.samba.org/index.php/User_Documentation  
# 更多文档请查阅：

Port related bug reports can go to the https://gitlab.com/samba-freebsd/ports/-/issues or  
# 和 FreeBSD port 相关问题请提交到：

to the FreeBSD Bugzilla https://bugs.freebsd.org/

# 所有 Samba 本身相关的问题请提交到：
All Samba related bug reports should go to the: https://bugzilla.samba.org/  
```

## 相关相关项目结构

```sh
/
├── usr
│   └── local
│       ├── etc
│       │   └── smb4.conf                # Samba 主配置文件
│       └── bin
│           ├── samba-tool               # Samba 初始化脚本
│           └── samba-nsupdate           # Samba DNS 更新工具
├── var
│   ├── db
│   │   └── samba4                       # Samba 相关数据库目录
│   └── log
│       └── samba4                       # Samba 日志目录
├── etc
│   ├── rc.conf                           # 系统启动配置文件
│   ├── resolv.conf                       # DNS 解析配置文件
│   ├── sysctl.conf                        # 系统参数配置文件
│   └── nsswitch.conf                      # 名称服务切换配置文件
└── samba
    └── testshare                         # Samba 共享目录
```

## 基础配置

安装完成后，需要进行基本配置才能使用 Samba。

* 将 Samba 服务设置为开机自动启动：

```sh
# service samba_server enable
```

* 创建 `/usr/local/etc/smb4.conf`，添加如下内容并保存

```ini
[global]
    min protocol = SMB2

[root]
    comment = root's stuff
    path = /root
    public = no
    browseable = yes
    writable = yes
    printable = no
    create mask = 0755
```

注释说明：

* `[global]`：全局配置段，适用于所有共享项。
* `min protocol = SMB2`：将最小支持协议限制为 SMB2，以方便高版本 Windows 访问。
* `[root]`：定义一个名为 `root` 的共享。
* `comment = root's stuff`：该共享的描述信息，Windows 浏览器中可见。
* `path = /root`：共享的实际路径是 `/root`，**不推荐** 在实际环境中共享该目录。
* `public = no`：不允许匿名访问（等同于 `guest ok = no`）。
* `browseable = yes`：可在网络邻居中浏览共享。
* `writable = yes`：允许客户端对该目录进行写入。
* `printable = no`：不是打印机共享。
* `create mask = 0755`：新建文件默认权限为 755，所有者读写，组和其他用户只读。

***

* 创建 samba root 用户，并配置密码：

```sh
# smbpasswd -a root	    # 为 Samba 用户 root 设置密码
```

* 启动 Samba 服务

```sh
# service samba_server start 
```

* 查看 Samba 服务的运行状态：

```sh
# service samba_server status
nmbd is running as pid 1520.
smbd is running as pid 1525.
```

* 在 Windows 下使用如下命令访问共享文件夹（以实际 IP 为准，请勿照抄！）。

在 Windows 系统中访问共享文件夹的操作说明：按下 Windows 键 + **R**（小写 r 也可）打开“运行”对话框。

在对话框中输入以下路径（请将示例 IP 地址和共享文件夹名替换为实际值），访问网络共享资源：`\\192.168.179.150`。

```batch
\\192.168.179.150
```

![Windows 访问网络共享资源](https://338876981-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCJR3FQGH1PkdRtOljuxb%2Fuploads%2Fgit-blob-2eaa5c9adb96ebc3b7ffdf60ce8e6441911b905c%2Fsamba1.png?alt=media)

输入刚才创建的用户名 `root`，以及密码：

![键入 Samba 用户名](https://338876981-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCJR3FQGH1PkdRtOljuxb%2Fuploads%2Fgit-blob-7d303fd907d0f1effb3aa8cbeced21f408dac0d5%2Fsamba2.png?alt=media)

连接成功：

![连接 Samba](https://338876981-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCJR3FQGH1PkdRtOljuxb%2Fuploads%2Fgit-blob-8f1733714a5c7a7dea6d3fc6ce778de6150c2cd9%2Fsamba3.png?alt=media)

## 域成员配置

### 网络地址配置

使用以下命令配置：

```sh
# bsdconfig
```

### 主机名设置

在安装系统的时候应该都配置了主机名，你可以在 `/etc/rc.conf` 文件编辑设置主机名为 `fb`：

```ini
hostname="fb"
```

### 域名系统配置

编辑 `/etc/resolv.conf` 文件，写入：

```ini
# Generated by resolvconf
search SVROS.COM                # 设置默认搜索域为域控制器域名
# nameserver 192.168.253.2

nameserver 192.168.253.130     # 设置域控制器的 IP 地址
nameserver 223.5.5.5            # 配置备用 DNS 服务器
nameserver 127.0.0.1            # 本地主机 DNS
options edns0                   # 启用扩展 DNS 功能
```

### 系统参数调优

```sh
# echo "kern.maxfiles=25600" >> /etc/sysctl.conf        # 设置系统最大打开文件数
# echo "kern.maxfilesperproc=16384" >> /etc/sysctl.conf # 设置每个进程最大打开文件数
# echo "net.inet.tcp.sendspace=65536" >> /etc/sysctl.conf  # 设置 TCP 发送缓冲区大小
# echo "net.inet.tcp.recvspace=65536" >> /etc/sysctl.conf  # 设置 TCP 接收缓冲区大小
```

### Kerberos 认证配置

```ini
[libdefaults]
    default_realm = SVROS.COM        # 设置 Kerberos 默认域名
    dns_lookup_realm = true          # 启用通过 DNS 查找域
    dns_lookup_kdc = true            # 启用通过 DNS 查找 KDC
    ticket_lifetime = 24h            # 设置票据有效期为 24 小时
    renew_lifetime = 7d              # 设置票据可续期时间为 7 天
    forwardable = yes                # 允许票据可转发
```

### 名称服务切换配置

配置 NSS 使用本地文件和 Winbind 进行用户信息查询：

```sh
# sed -i '' -e "s/^passwd:.*/passwd: files winbind/" /etc/nsswitch.conf
```

配置 NSS 使用本地文件和 Winbind 进行组信息查询：

```sh
# sed -i '' -e "s/^group:.*/group: files winbind/" /etc/nsswitch.conf
```

### Samba 主配置文件

```ini
[global]
	workgroup = SVROS
	server string = Samba Server Version %v
	security = ads
	realm = SVROS.COM
	domain master = no
	local master = no
	preferred master = no
	socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
	use sendfile = true

	idmap config * : backend = tdb
	idmap config * : range = 100000-299999
	idmap config SVROS : backend = rid
	idmap config SVROS : range = 10000-99999
	winbind separator = +
	winbind enum users = yes
	winbind enum groups = yes
	winbind use default domain = yes
	winbind nested groups = yes
	winbind refresh tickets = yes
	template homedir = /home/%D/%U
	template shell = /bin/false

	client use spnego = yes
	client ntlmv2 auth = yes
	encrypt passwords = yes
	restrict anonymous = 2
	log file = /var/log/samba4/log.%m
	max log size = 50

#============================ 自定义共享信息 ==============================

[testshare]
	comment = Test share
	path = /samba/testshare
	read only = no
	force group = "Domain Users"
	directory mode = 0770
	force directory mode = 0770
	create mode = 0660
	force create mode = 0660
```

上文“testshare”共享配置中最后两行用于优化实际使用权限（可选）

```ini
create mode = 0750
force create mode = 0750
```

### 域加入操作

```sh
net ads join --no-dns-updates -U administrator   # 将主机加入 Active Directory 域，不更新 DNS
net ads testjoin                                 # 测试主机是否成功加入域
# 应输出 "Join is OK"
# 在域控制器上，打开 DNS 管理控制台（MMC），为 BSD 服务器添加一条 "A" 记录，以便客户端能够找到该服务器
```

### 服务自启动配置

```sh
# echo "samba_server_enable=YES" >> /etc/rc.conf   # 设置 Samba 服务开机自动启动
# echo "winbindd_enable=YES" >> /etc/rc.conf      # 设置 Winbind 服务开机自动启动
```

### Kerberos 认证验证

```sh
kinit administrator   # 使用管理员账户获取 Kerberos 票据，输入密码后应无错误并返回提示符
klist                  # 查看当前 Kerberos 票据缓存
# 输出示例：
Credentials cache: FILE:/tmp/krb5cc_0
    Principal: administrator@SVROS.COM

Issued                Expires               Principal
Dec  6 10:15:39 2021  Dec  7 10:15:39 2021  krbtgt
```

### Winbind 服务验证

```sh
wbinfo -u
# 应该会返回域用户列表

wbinfo -g
# 应该会返回域用户组列表

getent passwd
# 用户列表末尾应包含 UID 大于 10000 的域用户

getent group
# 用户组列表末尾应包含 GID 大于 10000 的域用户组
```

如果 wbinfo 命令显示报错，重启 Samba 服务：

```sh
# service samba_server restart
```

### 共享目录配置

```sh
# mkdir -p /samba/testshare                                # 创建共享目录
# chown "administrator:domain users" /samba/testshare   # 设置目录所有者为 administrator，组为 domain users
# chmod 0770 /samba/testshare                              # 设置目录权限为所有者和组可读写执行，其他用户无权限
```

如果仅允许属主可读写，属组只读，可使用以下命令设置：

```sh
# chmod 0750 /samba/testshare	# 设置目录权限为所有者可读写执行，组可读执行，其他用户无权限
```

如果仅允许属主可读写，属组和其他用户不可访问，可使用以下命令设置：

```sh
# chmod -R 0700 /samba/testshare	# 递归设置目录及其内容权限为仅所有者可读写执行
```

## 故障排除与未竟事宜

Samba 日志文件位于 `/var/log/samba4`。

## 课后习题

1. 在 FreeBSD 上配置 Samba 作为 Active Directory 域控制器，创建测试用户和组，验证 Windows 客户端可正常加入域并访问共享资源。
2. 分析 Samba 的 smbd 与 nmbd 双守护进程架构，查看其职责划分与通信机制。
3. 修改 Samba 的默认安全级别，从 user 改为 share，验证行为变化。
