本文用于记录搭建一个可在windows以及其他操作系统下访问的远端smb网盘服务。
起因
由于不让使用自己的mac办公,在windows下工作了很长一段时间,期间,因为要使用linux,而不管是wsl还是wsl2都很坑的情况下,已经习惯用hyper-v架设一台虚拟机然后用ssh连接来办公,而在文件访问方面,突然发现用samba
来开启网络共享盘给Windows主机直接访问编辑东西很是方便,于是就对自己在家的ftp服务和空闲的主机打起了网盘的念头,是否可以自己创建一个远程的samba
服务来玩呢?答案是肯定的!而且非常简单,我们只需要:
一台windows或者linux主机,windows下就共享一个盘或者文件夹并设置用户权限,linux就用
apt install samba
然后配置共享来架设smb
服务,不管怎么样,这台主机就暴露了一个445
端口(可能还有137~139);一个拥有真实外网ip的网络环境,并且这个环境的WAN口映射是可控的,比如家庭可以和电信申请真实ip并用路由器拨号,公司的要请网管喝杯奶茶,最终你要能够在NAT设备出口把这台主机的445端口映射出外网IP;
准备好你的客户端,比如windows的
资源管理器
,mac的访达
,其他手机的什么app等等。
开始部署一个linux上的samba
windows上的smb服务很简单,因为smb是微软发明的,基本就是系统功能,也就是我们常说的共享
,我这里就搞个linux的吧,毕竟手上没有一直开机用的win主机。
很迅速的,我在老家的linux主机上搭建了samba
服务,并且,老家的网络环境是非常棒的静态公网ip,而且整栋楼的路由器我有密码,大概像这样:
安装samba
1
apt-get install samba -y
配置一个共享,放出参考,编辑
/etc/samba/smb.conf
,并在大概在注释Share Definitions
部分添加:1
2
3
4
5
6
7
8
9
10
11
12[smb_share]
comment = share
path = /root/smb-share
public = yes
browseable = yes
public = yes
read only = no
valid users = root
create mask = 0777
directory mask = 0777
force user = root
available = yes这一段例子表示,共享一个
共享名
为smb_share
的目录,目录地址为/root/smb-share
并且用户为root
(就是登录服务的用户),并且强制使用系统的root用户进行操作(这样不用考虑那么多权限问题)为叫root的smb账户并设置密码
1
smbpasswd -a root
按照提示完成密码的设置,这个密码就是后续客户端访问要输入的密码。
重启smbd服务
1
service smbd restart
这样,服务就搞好了。
打开路由器设置一个映射
上图我也把139映射出去了。这样一来,理论上,我在客户端直接访问这个ip地址就可以映射一个网络硬盘了。为了优雅,我还在我的一个子域名上绑定了这个ip。
445端口竟然无法访问
我打开了mac的访达
,直接按下cmd+k
,调出smb连接:
按下去,竟然无法连接,不信邪的我使用telnet
,竟然真的无法访问445端口。
考虑到这里,查了一下谷歌,发现原来445端口大部分运营商是不给用的,接着我就由在路由器加了一个映射,也就是446转445,前面的图也可以看到。访问时多加了446端口,于是成功了:
(为了方便我还设置了其他共享目录,在mac上连smb服务可以根据共享名
来挂载储存)。
我还用手机一款叫FX
的文件管理器创建了这一个一样的连接,这软件也是可以选择自定义smb端口的。
所以,整体的思路是:
重点来了,在windows上并没有办法访问非445端口的smb服务!
如上面所说的,445直接访问肯定是不行的,所以在windows的资源管理器
中,映射驱动器时加上了端口,结果直接无法访问了:
的确,经过谷歌等学习,在windows上,是不可能做到修改这个访问端口的,那我们要如何折腾,答案是有很多的,我们来分析一下,比如:
知乎上就有使用windows自带的端口转发命令,设置端口转发,让本机的127.0.0.1:445转发到目标也就是这个smb服务器ip的446端口去,这样,连接硬盘就只需要连接本机就好了。但这个方案有个很严重的问题,127.0.0.1:445本身如果是开启了共享的,那肯定是被占用的,对于平常来说,不管是家里面的还是公司的电脑,共享盘肯定是有的,所以这个方案不行。
于是还有说用上面的方法把445监听到
127.0.0.2
,不是很懂,但是没有成功,就像下图。还有一种方法就是用docker开启一个带nginx代理的容器,这个nginx使用tcp代理转发445端口,但是这样做,必须让宿主能直接访问到容器的ip地址,这个方案应该是可行的,但我没有尝试,因为在windows上用docker我是已经被坑过了,所以不管是工作还是平常,都不会安装docker。
所以最后,我使用上面的方案,但换成直接运行一个带有
独立ip
的虚拟主机,并运行nginx代理445端口。
开始一波操作:
打开hyper-v,创建了一个linux,并且配置了最低的性能,然后使用桥接模式的网络:
根据nginx官方安装了一个nginx,并且添加了关于
stream
模块的配置:在配置目录的根配置文件
nginx.conf
中添加:1
2
3
4
5
6
7
8
9stream {
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
# 统一放置,方便管理
include tcpConf/*.conf;
}这里意为
tcpConf
目录下的配置文件都是关于stream
的配置,接着我们创建这个目录,并添加具体的规则。在tcpConf下创建
xxx.conf
,写入:1
2
3
4
5
6
7
8
9
10
11upstream smbd_445 {
server xxx.xxx.xxx.xxx:446;
}
server {
listen 445;
proxy_connect_timeout 8s;
proxy_timeout 24h;
proxy_pass smbd_445;
}这样就是将这台机的445转发到目标446的反向代理了。
重新加载nginx,运行:
1
nginx -s reload
大功告成,查看端口,445已经在运行:
再回到windows的
资源管理器
中,对了,要给这个虚拟机设个固定ip比如我这里192.168.16.24,然后,直接映射这个ip,终于可以了:
玩到这里,就实现了在windows上连接一个非445端口的smb服务。
其他尝试的东西和总结
- 运营商不给访问445端口的时候,想过在云服务器上直接使用frp这种穿透工具映射445,结果发现,不管是GCP、digitalocean还是vultr等(国内的没试过,不过应该都一样),即使开放出445端口,telnet也是不通的,说明,这个445端口被封得狠。
- 在家里有一台弃用的手机一直用来做服务器,是通过
Termux
来运行的,但是Termux中安装的nginx竟然没有开启stream模块,需要自己编译,就没折腾,如果可以,那家里面的Windows电脑就不用浪费性能再安装虚拟机了。 - 这种搞法,在hyper-v上最少还要化半G内存来运行,不过现在内存多。
- windows的smb和samba还是不同的,应该是前者比较高级和安全,而且还有其他端口比如137-139这些是什么用的没有详细研究,两种服务细节上有什么区别也没有详细了解。
- 在工作中使用一个smb网盘还是有点方便的,在写一些不是git托管的东西,比如一些草稿性的文档,记录,表格等,可以直接丢上去,并且可以随时在手机,或者其他电脑上访问,而且因为是smb,操作和交互要比FTP好非常多。