问题: 场景是 一台内网Linux服务器,IP地址为 172.17.0.1
,在这台服务器上搭建了 vsftp服务;假设公网IP为 1.1.1.1
,为了能在互联网上 ssh 连接到服务器,对这台服务器 做了 ssh 端口的映射;对 ftp 的通信端口做端口映射;我们要在公网上能够实现 ftp的连接和文件上传
1、使用 fileZilla
连接ftp,发现显示登录成功,但是一直卡在读取目录那里
原因是因为没有映射 ftp 的数据端口,修改 vsftp.conf 将被动模式的数据端口 max 和 min 设置成同一个值 就可以实现固定端口。
ftp 有两种模式:主动模式和被动模式。可参考:https://blog.lacknb.cn/articles/2021/06/18/1624026653742.html#toc_h2_1
然后发现 可以成功读取目录,但是会提示 服务器发回了不可路由的地址。使用服务器地址代替。
这里后面会解释;
2、使用代码写ftp上传的时候,发现能连接成功,但是无法上传
原因:连接成功之后,服务器会将它的地址和数据端口返回到客户端,代表客户端可以向这个地址的这个端口传输文件了,当客户端拿到地址后,是无法上传文件的;因为返回的地址 是内网地址,解决办法就是 这里要判断下 服务器端传来的地址 是否和原来的地址(一开始配置的公网IP)一样,如果不一样了,要把这个地址换成公网 IP;
所以fileZilla 工具会一直提示 服务器发回了不可路由的地址。使用服务器地址代替。
<!-- 集成ftp-->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
对于这个工具,已经帮我们处理好这些了,最新版有更改,这里放的代码是旧版本的
if (__passiveNatWorkaround) {
try {
InetAddress host = InetAddress.getByName(__passiveHost);
// reply is a local address, but target is not - assume NAT box changed the PASV reply
if (host.isSiteLocalAddress()) {
InetAddress remote = getRemoteAddress();
if (!remote.isSiteLocalAddress()){
String hostAddress = remote.getHostAddress();
fireReplyReceived(0,
"[Replacing site local address "+__passiveHost+" with "+hostAddress+"]\n");
__passiveHost = hostAddress;
}
}
} catch (UnknownHostException e) { // Should not happen as we are passing in an IP address
throw new MalformedServerReplyException(
"Could not parse passive host information.\nServer Reply: " + reply);
}
}
public boolean isSiteLocalAddress() {
// refer to RFC 1918
// 10/8 prefix
// 172.16/12 prefix
// 192.168/16 prefix
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 10)
|| ((((address >>> 24) & 0xFF) == 172)
&& (((address >>> 16) & 0xF0) == 16))
|| ((((address >>> 24) & 0xFF) == 192)
&& (((address >>> 16) & 0xFF) == 168));
}
最新版本的代码有所不同
950行