背景

迫于不能浪费宿舍联通宽带的公网 IP,我用树莓派搭建了一个 NAS,使用 Samba 提供访问。但是,由于运营商限制,入站和出站的 139、445 端口都被封禁(对!你不能访问其他机器的 445 端口!),这样做只能让同一个局域网的服务访问。我尝试修改了端口号,把本地的 445 端口映射到公网的其它端口,算是可以给大部分 Samba 客户端使用了(比如安卓手机)。但是,Windows 的 Samba 客户端,并不支持设置端口号(如果在文件管理器地址栏输入 \\a.b.c.d:xxx 将会被认为是 WebDAV 协议)。

网上某些教程说,在 Windows 本地设置端口转发,把访问本机 445 端口的流量转发至你的 Samba 服务器端口。但是,这样做需要关闭 Windows 自己的 Samba 服务器,会导致网络共享、网络打印机等很多功能无法使用,导致莫名其妙的问题,所以不推荐。

但是可以换个思路。

原理

既然不能使用本机(127.0.0.1)做转发,那么为什么不使用本地网络中其他的机器进行数据转发呢?一开始我想在本地网络中加一个树莓派之类的小主机,但觉得这样太累赘了。虚拟机也是独立的机器,我觉得一样有效。

所以,只要在虚拟机里面装一个反向代理应用(Nginx),把发往虚拟机 445 端口的流量转发到 Samba 服务器,然后使用 Windows Samba 客户端访问这个虚拟机,就等于访问 Samba 服务器。

实践

这里,我使用了 Windows Hyper V,创建了 Ubuntu 20.04 Server 虚拟机(直接下载官方 ISO),然后使用默认交换机作为虚拟机的网络。

Snipaste_2020-04-28_14-07-57.png

启动后,安装系统,然后除了更新镜像源、安装 Nginx,什么都不用做。

1
2
sudo apt update
sudo apt install nginx

装好 Nginx 后,修改配置文件:

1
vim /etc/nginx/nginx.conf

添加一个 stream 模块,大致像下面:

1
2
3
4
5
6
7
8
9
10
11
12
http {
......
}

stream {
server {
listen 445;

// 你的 NAS 地址
proxy_pass mynas.example.com:12345;
}
}

然后重启 Nginx:

1
sudo nginx -s reload

转发的模块就做好了。

然后,再在 Windows 中打开 \\<虚拟机的ip>\<samba 路径(可选)> 就完成了。虚拟机 ip 可以在虚拟机里面用 ifconfig 命令查看。

后续

也许可以用 docker 实现,但我还没想好怎么搞。