NFS和Samba

Linux和Windows的文件共享, NFS和Samba (SMB)

NFS

前面在说ftp文件共享的时候我们提到了NFS是Linux/Unix上一个常用的文件共享服务中的一种. NFS的全称是Network File System. 一般情况下, 文件系统在内核中实现, 但并不是说文件系统不能在用户空间实现, 例如分布式的一些文件系统, 特别是一些网络文件系统和虚拟文件系统, 在内核中由一个叫FUSE的模块专门用来实现这个, 当然这不是这篇文章的重点. NFS是在内核中实现的, 在编译内核的时候就有这个选项的配置.

NFS中最大的问题就是在对本地文件系统的接口调用要被映射到网络上的另外一台主机上. 这是如何实现的?

在很久很久之前我们曾经提到过RPC, 远程过程调用的概念. 我们在内核上实现了很多系统调用, 当用户空间的程序需要进行特权操作的时候, 会发起系统调用, 这是本地系统调用 例如 ( read(), write(), open(), close() ) 而所谓远程过程调用其实就是把这个原本的过程调用发给远端主机. 当然这个也是需要监听在某个套接字的. 接受到了传过来的函数和参数的时候, 就会通过这个服务进程来托付给远端的OS 其实就相当于是对于远端机器的本地系统调用.当执行结束了之后, 这个执行结果就会返回给这个监听服务进程, 接着该进程再将结果构造成响应报文发送给发起调用的主机. 这就是RPC. 从本质讲他还是系统调用, 一部分的功能交给了本地程序, 一部分交给了远程主机的函数.

这个基本上就是NFS的工作模式, 当你对文件系统发起操作的时候, 内核中的NFS模块会得到响应, 尽管要操作的目录的本地并不存在, 但是NFS模块会帮助你从远端拿到结果并返回给你. 那么我们知道, 只要涉及到跨主机的情况, 为了能够使得双方得到兼容, 或者说双方都可以明确意思, 就需要协议的帮助, 或者使用半结构化的数据, 例如xml, json, http(RESTful)等.

在早期的NFS版本中, 有个非常棘手的问题, 就是文件权限的问题. 想象在本地主机test(uid=1002)用户存储了一个文件到远端主机上, 但是问题是远端主机上没有test这个用户啊? 这怎么办? 好办! 我们说过用户和组的本质只是一个ID号, 那么只要在远端主机上直接看到的就是1002这个ID号就行了, 但是, 巧合的是远端主机上正好有一个叫centos的用户的ID号也是1002, 这样子就乱套了. 除此之外, 我们知道root用户的ID号是0, 而在每一台主机上都是如此, 所以root用户就还是拥有可以操作远端一切文件的权限了.

因此, NFS的解决方法是进行权限的集中管理, 并且进行root的权限挤压, 也就是说, 当收到root用户存储的文件时, 会自动将这个root用户挤压成一个权限最小的用户, 来避免权限问题. 而用户不同的问题使用了一个新的机制, 叫做NIS.

NIS的全称是Network Information System, 如他的名字一样, 这个系统就像是一个信息库, 单独存放用户的账号信息. 我们知道进行登录是需要一个login程序的. 当我们输入了账号之后, login程序就会去找NIS去询问有没有这个账号啊? 如果有的话就显示password, 接着再将用户输入的密码发送给NIS询问密码是否正确 这样的一套工作流程. 问题终于解决了? 有意思的是, NIS协议是明文的. emmmmm, 所以NIS不建议在互联网上使用, 除此之外, NIS成为了这个网络的重要节点. 所以这样的缺点, 使得NIS的使用率并不高, 甚至说几乎没有在使用这个. 而现在使用的更多的是LDAP.

好吧, 我不使用NIS了. 现在怎么解决问题呢? 于是就想到了类似vsftpd的那种用户映射的模式, 在新版本的NFS中, 由一个叫做idmapd的服务端服务来完成这个事情, 实现用户账号的映射.

对于NFS来说, 另一个棘手的问题是用户认证这件事, 因为他只负责文件系统, 不能像其他的远程调用一样进行用户账号和密码的验证. 所以, NFS仅支持对于IP的认证. 但这又不安全而且很不灵活. 而且即使是这种认证也需要另外一个服务来跑, 这个认证服务叫做mountd, 他的主要作用就是令牌分发 当来访者请求发送到NFS服务器的时候, 这个请求会先交给mound服务, mountd判断这个用户是合法或者说有权限访问, 就发给他一个令牌, 这样每一对文件的操作只要令牌验证就可以了.

至此, 服务端已经运行三个daemon了: idmapd, mountd, nfsd. 客户端呢? 假设给你这样的场景, 如果有个疯子在你传输大文件的时候把你网线拔了, 你的文件传到一半怎么办? 这个时候就要求客户端进行文件跟踪以及文件锁的相关服务.

NFS监听在2049/udp, 2049/tcp端口上, 而mountd监听的端口就要由本地的公共服务rpc来决定了, 是一个随机端口. 但是这个随机端口是服务决定的, 所以是个半随机端口, 其实这个服务的名字叫做portmapper:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@WWW ~]# rpcinfo 
program version netid address service owner
100000 4 tcp6 ::.0.111 portmapper superuser
100000 3 tcp6 ::.0.111 portmapper superuser
100000 4 udp6 ::.0.111 portmapper superuser
100000 3 udp6 ::.0.111 portmapper superuser
100000 4 tcp 0.0.0.0.0.111 portmapper superuser
100000 3 tcp 0.0.0.0.0.111 portmapper superuser
100000 2 tcp 0.0.0.0.0.111 portmapper superuser
100000 4 udp 0.0.0.0.0.111 portmapper superuser
100000 3 udp 0.0.0.0.0.111 portmapper superuser
100000 2 udp 0.0.0.0.0.111 portmapper superuser
100000 4 local /var/run/rpcbind.sock portmapper superuser
100000 3 local /var/run/rpcbind.sock portmapper superuser

可以看到它监听在111端口上, 如果你无法看到或者无法使用, 应该先安装.

1
2
[root@WWW ~]# rpm -qf /sbin/rpcinfo 
rpcbind-0.2.0-42.el7.x86_64

接下来我们就来说说怎么使用nfs吧.

安装

1
2
3
[root@WWW ~]# rpm -q nfs-utils
package nfs-utils is not installed
[root@WWW ~]# yum install nfs-utils

接下来看看装了那些内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
[root@WWW ~]# rpm -ql nfs-utils
/etc/exports.d
/etc/gssproxy/24-nfs-server.conf
/etc/modprobe.d/lockd.conf
/etc/nfs.conf
/etc/nfsmount.conf
/etc/request-key.d/id_resolver.conf
/etc/sysconfig/nfs
/sbin/mount.nfs
/sbin/mount.nfs4
/sbin/osd_login
/sbin/rpc.statd
/sbin/umount.nfs
/sbin/umount.nfs4
/usr/lib/systemd/scripts/nfs-utils_env.sh
/usr/lib/systemd/system-generators/nfs-server-generator
/usr/lib/systemd/system/auth-rpcgss-module.service
/usr/lib/systemd/system/nfs-blkmap.service
/usr/lib/systemd/system/nfs-client.target
/usr/lib/systemd/system/nfs-config.service
/usr/lib/systemd/system/nfs-idmap.service
/usr/lib/systemd/system/nfs-idmapd.service
/usr/lib/systemd/system/nfs-lock.service
/usr/lib/systemd/system/nfs-mountd.service
/usr/lib/systemd/system/nfs-secure.service
/usr/lib/systemd/system/nfs-server.service
/usr/lib/systemd/system/nfs-utils.service
/usr/lib/systemd/system/nfs.service
/usr/lib/systemd/system/nfslock.service
/usr/lib/systemd/system/proc-fs-nfsd.mount
/usr/lib/systemd/system/rpc-gssd.service
/usr/lib/systemd/system/rpc-statd-notify.service
/usr/lib/systemd/system/rpc-statd.service
/usr/lib/systemd/system/rpcgssd.service
/usr/lib/systemd/system/rpcidmapd.service
/usr/lib/systemd/system/var-lib-nfs-rpc_pipefs.mount
/usr/sbin/blkmapd
/usr/sbin/exportfs
/usr/sbin/mountstats
/usr/sbin/nfsdcltrack
/usr/sbin/nfsidmap
/usr/sbin/nfsiostat
/usr/sbin/nfsstat
/usr/sbin/rpc.gssd
/usr/sbin/rpc.idmapd
/usr/sbin/rpc.mountd
/usr/sbin/rpc.nfsd
/usr/sbin/rpcdebug
/usr/sbin/showmount
/usr/sbin/sm-notify
/usr/sbin/start-statd
...(omitted)
/var/lib/nfs
/var/lib/nfs/etab
/var/lib/nfs/rmtab
/var/lib/nfs/rpc_pipefs
/var/lib/nfs/statd
/var/lib/nfs/statd/sm
/var/lib/nfs/statd/sm.bak
/var/lib/nfs/state
/var/lib/nfs/v4recovery
/var/lib/nfs/xtab

很显眼就能看到

  • /usr/sbin/rpc.idmapd
  • /usr/sbin/rpc.mountd
  • /usr/sbin/rpc.nfsd

这三个重要的服务端程序.

启动服务

现在就直接来启动, 要注意的是 这个时候的服务名字不是nfsd而是nfs:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@WWW ~]# systemctl start nfs
[root@WWW ~]# systemctl status nfs
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; disabled; vendor preset: disabled)
Active: active (exited) since Sat 2017-09-30 02:51:15 EDT; 6s ago
Process: 9826 ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS (code=exited, status=0/SUCCESS)
Process: 9821 ExecStartPre=/bin/sh -c /bin/kill -HUP `cat /run/gssproxy.pid` (code=exited, status=0/SUCCESS)
Process: 9820 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
Main PID: 9826 (code=exited, status=0/SUCCESS)
CGroup: /system.slice/nfs-server.service

Sep 30 02:51:15 WWW systemd[1]: Starting NFS server and services...
Sep 30 02:51:15 WWW systemd[1]: Started NFS server and services.

这个时候该启动的程序都已经在自己监听的套接字上了:

1
2
3
4
5
6
[root@WWW ~]# netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:49287 0.0.0.0:* LISTEN 9806/rpc.statd
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd
tcp 0 0 0.0.0.0:20048 0.0.0.0:* LISTEN 9819/rpc.mountd

而且这个时候再调用rpcinfo, 就可以看到一大堆端口了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
[root@WWW ~]# rpcinfo 
program version netid address service owner
100000 4 tcp6 ::.0.111 portmapper superuser
100000 3 tcp6 ::.0.111 portmapper superuser
100000 4 udp6 ::.0.111 portmapper superuser
100000 3 udp6 ::.0.111 portmapper superuser
100000 4 tcp 0.0.0.0.0.111 portmapper superuser
100000 3 tcp 0.0.0.0.0.111 portmapper superuser
100000 2 tcp 0.0.0.0.0.111 portmapper superuser
100000 4 udp 0.0.0.0.0.111 portmapper superuser
100000 3 udp 0.0.0.0.0.111 portmapper superuser
100000 2 udp 0.0.0.0.0.111 portmapper superuser
100000 4 local /var/run/rpcbind.sock portmapper superuser
100000 3 local /var/run/rpcbind.sock portmapper superuser
100024 1 udp 0.0.0.0.232.28 status 29
100024 1 tcp 0.0.0.0.192.135 status 29
100024 1 udp6 ::.164.187 status 29
100024 1 tcp6 ::.233.229 status 29
100005 1 udp 0.0.0.0.78.80 mountd superuser
100005 1 tcp 0.0.0.0.78.80 mountd superuser
100005 1 udp6 ::.78.80 mountd superuser
100005 1 tcp6 ::.78.80 mountd superuser
100005 2 udp 0.0.0.0.78.80 mountd superuser
100005 2 tcp 0.0.0.0.78.80 mountd superuser
100005 2 udp6 ::.78.80 mountd superuser
100005 2 tcp6 ::.78.80 mountd superuser
100005 3 udp 0.0.0.0.78.80 mountd superuser
100005 3 tcp 0.0.0.0.78.80 mountd superuser
100005 3 udp6 ::.78.80 mountd superuser
100005 3 tcp6 ::.78.80 mountd superuser
100003 3 tcp 0.0.0.0.8.1 nfs superuser
100003 4 tcp 0.0.0.0.8.1 nfs superuser
100227 3 tcp 0.0.0.0.8.1 nfs_acl superuser
100003 3 udp 0.0.0.0.8.1 nfs superuser
100003 4 udp 0.0.0.0.8.1 nfs superuser
100227 3 udp 0.0.0.0.8.1 nfs_acl superuser
100003 3 tcp6 ::.8.1 nfs superuser
100003 4 tcp6 ::.8.1 nfs superuser
100227 3 tcp6 ::.8.1 nfs_acl superuser
100003 3 udp6 ::.8.1 nfs superuser
100003 4 udp6 ::.8.1 nfs superuser
100227 3 udp6 ::.8.1 nfs_acl superuser
100021 1 udp 0.0.0.0.220.82 nlockmgr superuser
100021 3 udp 0.0.0.0.220.82 nlockmgr superuser
100021 4 udp 0.0.0.0.220.82 nlockmgr superuser
100021 1 tcp 0.0.0.0.182.24 nlockmgr superuser
100021 3 tcp 0.0.0.0.182.24 nlockmgr superuser
100021 4 tcp 0.0.0.0.182.24 nlockmgr superuser
100021 1 udp6 ::.217.178 nlockmgr superuser
100021 3 udp6 ::.217.178 nlockmgr superuser
100021 4 udp6 ::.217.178 nlockmgr superuser
100021 1 tcp6 ::.142.205 nlockmgr superuser
100021 3 tcp6 ::.142.205 nlockmgr superuser
100021 4 tcp6 ::.142.205 nlockmgr superuser

如果此时重启, 端口就会发生改变. 因为这是半随机的.

配置NFS

说了这么多, 其实配置才是最简单的, 只需要编辑/etc/exports文件, 来说明要导出的文件目录是哪一个就行了. 这个文件的具体格式是这样的:

dir(filesystem) client1(option1, option2) client2(option1, option2)

以及就是暴露出去哪个目录(或者文件系统, 但是文件系统就是挂载到目录上才可以使用的, 所以指定目录就行了), 接着允许访问的客户是谁, 以及他们的权限设定和选项.

所有支持的选项可以在exports的man手册上查看. 一个最简单的例子就像这样:

/tmp 192.168.56.103(rw)

接着我们重启服务 ( 这里先进行重启, 但是这是一种极其不推荐的做法, 后面再细说 ) 接着就可以查看了, 使用命令:

1
2
3
[root@WWW etc]# showmount -e 192.168.56.101
Export list for 192.168.56.101:
/tmp 192.168.56.103

在另外一台主机上也是可以查看到的:

1
2
3
4
5
6
7
8
[root@WWW ~]# ip addr show enp0s3 
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:a0:b9:10 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.103/24 brd 192.168.56.255 scope global dynamic enp0s3
valid_lft 1161sec preferred_lft 1161sec
[root@WWW ~]# showmount -e 192.168.56.101
Export list for 192.168.56.101:
/tmp 192.168.56.103

当然前提是安装了nfs-utils这个包.

现在其实已经配置完成了, 登录到103主机挂载即可使用了.

1
2
3
4
5
6
7
8
9
[root@WWW ~]# mount -t nfs 192.168.56.101:/tmp /mnt/
[root@WWW ~]# cd /mnt/
[root@WWW mnt]# ls
fstab yum_save_tx.2017-09-23.17-39.rZFKGX.yumtx yum_save_tx.2017-09-26.11-33.JDsQeW.yumtx
functions yum_save_tx.2017-09-24.02-10.SFv1gg.yumtx yum_save_tx.2017-09-28.02-22.TmlpEK.yumtx
grub.cfg yum_save_tx.2017-09-24.02-14.hLrGaJ.yumtx yum_save_tx.2017-09-28.02-24.nw6FJ3.yumtx
systemd-private-76aa5be0b609474b906e0041c7287281-named.service-YvkHEW yum_save_tx.2017-09-24.02-17.jrTroG.yumtx yum_save_tx.2017-09-28.02-26.eetkNP.yumtx
systemd-private-84ee57e9e1d94742bc1ef6e525e7c6f9-named.service-bGtSvY yum_save_tx.2017-09-24.02-25.z2khA_.yumtx
yum_save_tx.2017-09-23.17-39.CI1ETc.yumtx yum_save_tx.2017-09-26.11-32.zTDVHS.yumtx

怎么样是不是很帅气 !

那么就来说说几个常用的参数吧. 除了简单的读写权限, 还有很多有趣的属性呢

  • async: 异步读写, 可以提高性能.
  • secure: 使用1024以下的端口
  • root_squash: root权限挤压
  • all_squash: 所有用户都积压权限
  • anonuid=?, anongid=?: 所有的文件所属用户和组都是匿名

现在就来说一下, 如何正常的进行文件系统导出, 不是进行重启服务, 而是使用一个特定的工具: exportfs

我们先加上一个新的文件系统导出:

1
2
3
4
5
6
7
8
9
10
[root@WWW tmp]# mkdir -p /share/nfs
[root@WWW tmp]# vim /etc/exports
[root@WWW tmp]# showmount -e 192.168.56.101
Export list for 192.168.56.101:
/tmp 192.168.56.103
[root@WWW tmp]# exportfs -ar
[root@WWW tmp]# showmount -e 192.168.56.101
Export list for 192.168.56.101:
/share/nfs 192.168.56.103
/tmp 192.168.56.103

-ar就是说all re-export, 另外还支持其他的参数例如 -u 关闭导出的文件系统, 可以和-a参数连在一起使用, 表示关闭所有的文件系统.

当然我们也可以进行开机自动挂载nfs文件系统, 只要在fstab中写上就行了. 直接mount也可以看到当前的参数:

1
2
...(omitted)
192.168.56.101:/tmp on /mnt type nfs4 (rw,relatime,vers=4.1,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.56.103,local_lock=none,addr=192.168.56.101)

Samba

前面说的NFS, 如果想要使用, 最好是Unix/Linux系统, Windows对于NFS的支持还是很有限的. 更早之前, 我们还说过FTP这个协议, 但是FTP位于应用层, 从协议本身来看, 把一个FTP共享挂载在客户机上, 这是不可能的.

这两者就催生了samba的诞生, 为了使得能够在Linux/Unix上实现一个能够提供Windows支持的协议, 于是这就是Windows上的smb, 即Service Message Block. 这个就是Windows上网络邻居之间共享文件所使用到的, 它的协议通称CIFS, 即Common Internet File System. 一段时间之后smb协议逐渐演化成一个开源项目, 这个项目的命名就是samba.

samba可以安装在Win和Unix/Linux主机上. 在Windows上, 这个服务监听137/udp, 138/tcp, 139/tcp, 445/tcp.

具体说来, 在137,138是用来实现NetBIOS的, 这个是Windows用来基于主机名进行互相访问的, 对于主机名的解析, 依靠Windows的Wins服务解析服务, 除此之外, Windows的网络共享模型有基于工作组和基于域的, 这些都需要特定的服务来支持. 对于Linux/Unix主机, 如果想要加入Windows, 就必须也实现这些服务.

samba就做了这些事情, 它主要实现了三种服务: nmdb: 提供NetBIOS服务, smbd: 提供CIFS协议支持, winbindd: 提供对Windows用户组的支持.

接下来我们使用一个CentOS6和和一台Windows XP做实验:

先来看看CentOS6上的软件包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@localhost ~]# yum list all samba*
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
base | 3.7 kB 00:00
extras | 3.4 kB 00:00
updates | 3.4 kB 00:00
Installed Packages
samba-client.x86_64 3.5.10-114.el6 @base/$releasever
samba-common.x86_64 3.5.10-114.el6 @base/$releasever
samba-winbind-clients.x86_64 3.5.10-114.el6 @base/$releasever
Available Packages
samba.x86_64 3.6.23-45.el6_9 updates
samba-client.x86_64 3.6.23-45.el6_9 updates
samba-common.i686 3.6.23-45.el6_9 updates
samba-common.x86_64 3.6.23-45.el6_9 updates
samba-doc.x86_64 3.6.23-45.el6_9 updates
samba-domainjoin-gui.x86_64 3.6.23-45.el6_9 updates
samba-glusterfs.x86_64 3.6.23-45.el6_9 updates
samba-swat.x86_64 3.6.23-45.el6_9 updates
samba-winbind.x86_64 3.6.23-45.el6_9 updates
samba-winbind-clients.i686 3.6.23-45.el6_9 updates
samba-winbind-clients.x86_64 3.6.23-45.el6_9 updates
samba-winbind-devel.i686 3.6.23-45.el6_9 updates
samba-winbind-devel.x86_64 3.6.23-45.el6_9 updates
samba-winbind-krb5-locator.x86_64 3.6.23-45.el6_9 updates
samba4.x86_64 4.2.10-11.el6_9 updates
samba4-client.x86_64 4.2.10-11.el6_9 updates
samba4-common.x86_64 4.2.10-11.el6_9 updates
samba4-dc.x86_64 4.2.10-11.el6_9 updates
samba4-dc-libs.x86_64 4.2.10-11.el6_9 updates
samba4-devel.x86_64 4.2.10-11.el6_9 updates
samba4-libs.x86_64 4.2.10-11.el6_9 updates
samba4-pidl.x86_64 4.2.10-11.el6_9 updates
samba4-python.x86_64 4.2.10-11.el6_9 updates
samba4-test.x86_64 4.2.10-11.el6_9 updates
samba4-winbind.x86_64 4.2.10-11.el6_9 updates
samba4-winbind-clients.x86_64 4.2.10-11.el6_9 updates
samba4-winbind-krb5-locator.x86_64 4.2.10-11.el6_9 updates

有两个版本的samba, 系统已经预先安装了samba客户端, 3.6版本. 那么我们就使用这个版本的吧.

在Windows上, 共享文件路径是这样写的: \SEREVR\shared_name.

下面说说我们当前的环境:

cmd1

而另外一台CentOS6主机就是那个192.168.56.101. 现在在Windows上建立一个共享文件夹, 步骤如下:

  • 关闭简单文件共享

easy

  • 设置共享文件夹

shared

  • 配置权限, 创建一个新用户

confshared

完成之后就会看到图标发生改变.

现在就来试试连接到Windows上的共享文件夹, 首先我们来看看samba-client安装了什么二进制程序吧:

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# rpm -ql samba-client
/usr/bin/findsmb
/usr/bin/nmblookup
/usr/bin/rpcclient
/usr/bin/sharesec
/usr/bin/smbcacls
/usr/bin/smbclient
/usr/bin/smbget
/usr/bin/smbprint
/usr/bin/smbspool
/usr/bin/smbtar
/usr/bin/smbtree

其中我们最关心的就是那个smbclient了. 使用这个程序可以列出目标主机的共享目录, 以及进行连接, 接着就像是使用ftp客户端一样了.

来试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@localhost ~]# smbclient -L 192.168.56.102 -U test
Enter test's password:
session request to 192.168.56.102 failed (Called name not present)
Domain=[NETCOOL-TEST] OS=[Windows 5.1] Server=[Windows 2000 LAN Manager]

Sharename Type Comment
--------- ---- -------
IPC$ IPC 远程 IPC
Shard Disk This is a teest
ADMIN$ Disk 远程管理
C$ Disk 默认共享
Shared Disk This is a test.
session request to 192.168.56.102 failed (Called name not present)
session request to 192 failed (Called name not present)
Domain=[NETCOOL-TEST] OS=[Windows 5.1] Server=[Windows 2000 LAN Manager]

Server Comment
--------- -------

Workgroup Master
--------- -------

默认就有很多共享服务, 在最后一行的那个就是我们的新建的Shared文件夹, 可以往里面扔东西, 因为刚刚我给了test用户写入的权限, 使用上面说的路径来连接: [ 为了防止各种各样的辣鸡NT权限报错,建议把测试文件夹放在别的分区或者共享文档目录下 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@localhost ~]# smbclient //192.168.56.102/Shared -U test
Enter test's password:
session request to 192.168.56.102 failed (Called name not present)
Domain=[NETCOOL-TEST] OS=[Windows 5.1] Server=[Windows 2000 LAN Manager]
smb: \> ls
. D 0 Mon Oct 2 19:55:36 2017
.. D 0 Mon Oct 2 19:55:36 2017

40915 blocks of size 262144. 26933 blocks available
smb: \> ?
? allinfo altname archive blocksize
cancel case_sensitive cd chmod chown
close del dir du echo
exit get getfacl hardlink help
history iosize lcd link lock
lowercase ls l mask md
mget mkdir more mput newer
open posix posix_encrypt posix_open posix_mkdir
posix_rmdir posix_unlink print prompt put
pwd q queue quit readlink
rd recurse reget rename reput
rm rmdir showacls setmode stat
symlink tar tarmode translate unlock
volume vuid wdel logon listconnect
showconnect .. !

是不是和ftp使用起来很像啊

向里面扔个文件:

1
2
3
smb: \> lcd /etc/
smb: \> put fstab
putting file fstab as \fstab (84.7 kb/s) (average 84.7 kb/s)

此时Windows中已经看到了:

sucshared

就这么简单. 这是一种基于交互式访问的方式,也可以进行挂载使用:

1
2
3
4
5
[root@localhost ~]# mount -t cifs //192.168.56.102/Shared /NTshared/ -o username=test
Password:
[root@localhost NTshared]# cd /NTshared/
[root@localhost NTshared]# ls
fstab

这很简单, 但是重点在于, 我们如何使Linux成为Samba服务器端, Windows成为客户端呢.

  • 首先安装服务器端程序
1
yum install samba -y

安装完成之后, 我们按照惯例查看安装了哪些, 其中最重要的就是下面的两守护进程了:

1
2
3
4
...(omitted)
/usr/sbin/nmbd
/usr/sbin/smbd
...(omitted)

启动samba服务的时候, 其实就是启动的这个. 他的主配置文件是/etc/samba/smb.conf

  • 接着我们需要进行认证的设置

与ftp相似的是, samba直接启动之后就可以使用. 但是不同的是, samba需要指定那些目录共享, 这其中有点像NFS. 我们在说ftp的时候说过, vsftpd维护三种用户: 系统用户匿名用户虚拟用户. 对于samba来说, 他只使用系统用户, 但是有意思的是, 他不是用shadow文件进行的密码认证, 而是使用自己的密码文件. 这就是说 账号使用passwd中的系统用户, 但是认证是自己来( 所以我可以理解成samba不使用Linux的统一认证pam(?) )

由一个工具专门做这个事情smbpasswd.

不多说了, 直接启动服务看看:

1
2
3
[root@localhost ~]# service nmb start && service smb start
Starting NMB services: [ OK ]
Starting SMB services: [ OK ]

接着就能看到监听的137,139,445端口已经开始监听起来了.

脱坑指南: 如果你的nmb进程启动有问题( 比如没法创建套接字 ), 那么就手动的nmbd -D启动.

这个时候按理说已经可以在Windows主机中看到Linux主机了, 但是问题在于他们的工作组不一样( 上面说过使用工作组来划分 ), 因为Windows上的默认工作组是WORKGROUP, 而samba默认的工作组是MYGROUP. 这个设定可以在samba的配置文件中进行更改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#======================= Global Settings =====================================

[global]

# ----------------------- Network Related Options -------------------------
#
# workgroup = NT-Domain-Name or Workgroup-Name, eg: MIDEARTH
#
# server string is the equivalent of the NT Description field
#
# netbios name can be used to specify a server name not tied to the hostname
#
# Interfaces lets you configure Samba to use multiple interfaces
# If you have multiple network interfaces then you can list the ones
# you want to listen on (never omit localhost)
#
# Hosts Allow/Hosts Deny lets you restrict who can connect, and you can
# specifiy it as a per share option as well
#
workgroup = MYGROUP
server string = Samba Server Version %v
...(omitted)

把他改成WORKGROUP之后, 重新启动服务, 在windows中的网上邻居中查看工作组的计算机就可以看到:
sambaserver

脱坑指南: 如果你看不到主机先尝试清空iptables.

但是这个时候还是连接不了的哦 因为这个时候我们还没有设置Samba的用户账户. 所以没法进行连接.

这个账号的设置就需要我们之前说过的smbpasswd了:

1
2
3
4
5
[root@localhost ~]# useradd smbuser1
[root@localhost ~]# smbpasswd -a smbuser1
New SMB password:
Retype new SMB password:
Added user smbuser1.

除了-a参数增加用户以外, 还有一些常用的选项:

1
2
3
4
5
[root@localhost ~]# smbpasswd
-a add user
-d disable user
-e enable user
-x delete user

输入密码登陆之后就可以看到了:

smbuser1

接着你就可以在里面创建文件了, 因为这就是smbuser1的家目录, 所以是有权限的.

另外如果是使用另外一台Linux来访问这个smbuser1是什么样子的呢?我们启动另外一台CentOS7来看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@WWW ~]# smbclient -L 192.168.56.101 -U smbuser1
Enter SAMBA\smbuser1's password:
Domain=[LOCALHOST] OS=[Unix] Server=[Samba 3.6.23-45.el6_9]

Sharename Type Comment
--------- ---- -------
IPC$ IPC IPC Service (Samba Server Version 3.6.23-45.el6_9)
smbuser1 Disk Home Directories
Domain=[LOCALHOST] OS=[Unix] Server=[Samba 3.6.23-45.el6_9]

Server Comment
--------- -------

Workgroup Master
--------- -------
WORKGROUP LOCALHOST

可以看出来咯, 默认的备注还是家目录.

还是回过头来看看配置文件吧:

1
2
3
4
5
6
7
        workgroup = WORKGROUP # 工作组
server string = Samba Server Version %v # 服务器描述
; netbios name = MYSERVER # 主机名
; interfaces = lo eth0 192.168.12.2/24 192.168.13.2/24 # 启用接口
; hosts allow = 127. 192.168.12. 192.168.13. # 访问控制白名单
log file = /var/log/samba/log.%m # 每一个进程都会有一个日志
max log size = 50 # 滚动限制

跳过后面的关于域的设定, 我们直接来看后面的共享设定:

1
2
3
4
5
6
[homes]
comment = Home Directories
browseable = no # 除了属主外是否可以浏览, 应该打开的
writable = yes # 是否可写
; valid users = %S
; valid users = MYDOMAIN\%S

第一行就是我们的注释设定, 在这里进行更改.

如果先要自定义一个共享, 首先就要确保由一个Path参数. 后面有示例.

不管怎么说, 我们现在就来手动创建一个分享吧:

1
2
3
4
5
6
7
[test]
comment = Shared test
path = /tmp/shared
public = yes
writable = yes
guest ok = yes
readonly = no

接着我们创建那个文件夹:

1
[root@localhost ~]# mkdir /tmp/shared

我们可以执行检查, 来确保配置文件不会出错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@localhost ~]# testparm 
Load smb config files from /etc/samba/smb.conf
rlimit_max: increasing rlimit_max (1024) to minimum Windows limit (16384)
Processing section "[homes]"
Processing section "[printers]"
Processing section "[test]"
Loaded services file OK.
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions

[global]
server string = Samba Server Version %v
log file = /var/log/samba/log.%m
max log size = 50
client signing = required
idmap config * : backend = tdb
cups options = raw

[homes]
comment = Home Directories
read only = No

[printers]
comment = All Printers
path = /var/spool/samba
printable = Yes
print ok = Yes
browseable = No

[test]
comment = Shared test
path = /tmp/shared
read only = No
guest ok = Yes

接着重启服务, 来进入另外一台CentOS7 试试看:

1
2
3
4
5
6
7
8
[root@WWW ~]# smbclient //192.168.56.101/test -U smbuser1
Enter SAMBA\smbuser1's password:
Domain=[LOCALHOST] OS=[Unix] Server=[Samba 3.6.23-45.el6_9]
smb: \> ls
. D 0 Mon Oct 2 15:16:31 2017
.. D 0 Mon Oct 2 15:19:02 2017

5715544 blocks of size 1024. 3492768 blocks available

没毛病.

温馨提示: 如果你看到的是:

1
2
smb: \> ls
NT_STATUS_ACCESS_DENIED listing \*

并且在上面的Windows实验中看到的是:

deny

而且你确定是有权限的话, 那么很大一部分原因可能是SELINUX.

Extra

另外, samba是有一个图形化管理工具的, 叫做swat. 处于extra源中.