转自 外网访问内网的FTP服务器

首先感谢作者给出的总结,原文是介绍Serv-U的,我针对FileZilla Server进行了稍微修改,仅看操作可直接跳到分割线后第3部分。

1. 背景简介
最近研究如何在内网搭架FTP服务器,同时要保证外网(公网)能访问的到。终成正果,但走了一些弯路,在此记下,以飨后人。

2. 基础知识
FTP 使用 2 个端口,一个数据端口和一个命令端口(也叫做控制端口)。这两个端口一般是21 (命令端口)和 20 (数据端口),当然你也可以自定义。控制 Socket 用来传送命令,数据 Socket 是用于传送数据。每一个 FTP 命令发送之后,FTP 服务器都会返回一个字符串,其中包括一个响应代码和一些说明信息。其中的返回码主要是用于判断命令是否被成功执行了。

2.1. 命令端口
一般来说,客户端有一个 Socket用来连接 FTP 服务器的相关端口,它负责 FTP 命令的发送和接收返回的响应信息。一些操作如“登录”、“改变目录”、“删除文件”,依靠这个连接发送命令就可完成。

2.2. 数据端口
对于有数据传输的操作,主要是显示目录列表,上传、下载文件,我们需要依靠另一个 Socket来完成。

如果使用被动模式,通常服务器端会返回一个端口号。客户端需要用另开一个 Socket 来连接这个端口,然后我们可根据操作来发送命令,数据会通过新开的一个端口传输。

如果使用主动模式,通常客户端会发送一个端口号给服务器端,并在这个端口监听。服务器需要连接到客户端开启的这个数据端口,并进行数据的传输。

下面对 FTP 的主动模式和被动模式做一个简单的介绍。

2.3. 主动模式(PORT)
主动模式下,客户端随机打开一个大于1024 的端口向服务器的命令端口 P,即 21 端口,发起连接,同时开放N +1 端口监听,并向服务器发出 “port N+1” 命令,由服务器从它自己的数据端口 (20) 主动连接到客户端指定的数据端口 (N+1)。

FTP 的客户端只是告诉服务器自己的端口号,让服务器来连接客户端指定的端口。对于客户端的防火墙来说,这是从外部到内部的连接,可能会被阻塞。

2.4. 被动模式(PASV)
为了解决服务器发起到客户的连接问题,有了另一种 FTP 连接方式,即被动方式。命令连接和数据连接都由客户端发起,这样就解决了从服务器到客户端的数据端口的连接被防火墙过滤的问题。

被动模式下,当开启一个 FTP 连接时,客户端打开两个任意的本地端口 (N > 1024 和 N+1) 。

第一个端口连接服务器的 21 端口,提交 PASV 命令。然后,服务器会开启一个任意的端口 (P > 1024 ),返回如“227 entering passive mode (127,0,0,1,4,18)”。 它返回了 227 开头的信息,在括号中有以逗号隔开的六个数字,前四个指服务器的地址,最后两个,将倒数第二个乘256 再加上最后一个数字,这就是 FTP 服务器开放的用来进行数据传输的端口。如得到 227 entering passive mode(h1,h2,h3,h4,p1,p2),那么端口号是 p1*256+p2,ip 地址为h1.h2.h3.h4。这意味着在服务器上有一个端口被开放。客户端收到命令取得端口号之后, 会通过 N+1 号端口连接服务器的端口 P,然后在两个端口之间进行数据传输。


3. 我走过的弯路
使用FileZilla Server搭架FTP服务器很简单,网上教程也很多,不再累述。我这里只记录下我遇到的问题。

3.1. 使用环境

 

操作系统

FTP软件

FTP软件版本

FTP服务器

Windows 10

FileZilla Server 0.9.60

FTP客户端

IOS 12.1 nPlayer  

FTP服务器安装在实验室内网的电脑上,FTP客户端在外网的电脑上(严格来说也是在另一外局域网内)。

3.2. PASV端口范围
被动模式(PASV)下,有数据要传输时,服务器会打开一个数据端口(并处于监听状态),然后告知客户端,客户端连接这个数据端口发送数据。但是数据端口是随机的,那么服务器该如何将这些随机数据端口映射到公网的路由器上呢???总不能让内部网的一台机器完全暴露到公网上吧,虽然确实有这样的方案(称之为DMZ主机),但这绝对是最愚蠢的选择。

这就是我遇到的第一个弯路,折腾了很久才知道。虽然数据端口是随机的,但FileZilla Server可以指定随机的范围。打开FileZilla Server Interface > Edit > Settings > Passive Mode Settings 。

勾选 use custom port range 并设置PASV范围,如下图所示,在这里就可以指定随见的范围了。你只要把这些端口映射到路由器就可以了。

图表 1 PASV 端口范围

3.3. PASV IP地址
我遇到的第二个难缠的问题是,FTP 客户端获取不到FTP服务器的目录列表。日志信息如下:

(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> Connected on port 21, sending welcome message...
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> 220-FileZilla Server 0.9.60 beta
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> 220-written by Tim Kosse (tim.kosse@filezilla-project.org)
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> 220-Please visit https://filezilla-project.org/
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> 220 From PeanutK
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> AUTH SSL
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> 502 Explicit TLS authentication not allowed
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> AUTH TLS
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> 502 Explicit TLS authentication not allowed
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> USER 947995721@qq.com
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> 331 Password required for 947995721@qq.com
(000001)2018/12/29 22:03:04 - (not logged in) (10.11.35.115)> PASS ****************
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> 230 Logged on
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> PWD
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> 257 "/" is current directory.
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> OPTS UTF8 ON
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> 202 UTF8 mode is always enabled. No need to send this command.
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> PASV
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> 227 Entering Passive Mode (192.168.137.1,234,98)
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> TYPE A
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> 200 Type set to A
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> LIST
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> 150 Opening data channel for directory listing of "/"
(000001)2018/12/29 22:03:04 - 947995721@qq.com (10.11.35.115)> 425 Can't open data connection for transfer of "/"

也是经过一阵折腾,最后突然发现服务器对PASV指令的响应是:227Entering Passive Mode (192.168.137.1,50,203),这里127,0,0,1是FTP服务器在内网IP,客户端自然连接不上。打开Serv-U管理控制台 > 你自定义的域名 > 域详细信息 > 监听器 > 编辑 ,在PASV IP地址或域名中设置公网IP即可。 如下图所示。

4. 总结
FTP服务器至少需要两个端口:命令端口和数据端口。命令端口是固定的,而数据端口是随机的。随机的端口如何映射到公网?FZ可以设置PASV端口范围,随机也只是在设定的范围内随机。另外需要设置PASV IP地址,否者服务器响应客户端的PASV 命令时,会把服务器在内网中的IP地址告知客户端,这个地址对应客户端来说是连接不上的。

外网访问内网的FTP服务器的更多相关文章

  1. 实现外网远程桌面内网的电脑和外网访问内网的FTP

     基于之前两篇文章搭建了ngrok实现了内网穿透,用过了http和https的协议完成了外网访问内网的网站,这一篇教大家用tcp协议实现外网远程桌面内网的电脑和外网访问内网的FTP. 一.外网远程桌面 ...

  2. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  3. 配置多层NAT和端口映射实现外网访问内网

    配置多层NAT和端口映射实现外网访问内网 背景和原理 通过配置NAT可以实现内网中不能直接访问外网的主机通过NAT代理访问内网,配置方法这里不再赘述(前文有介绍).本文以两层的NAT代理做模拟,通过端 ...

  4. SVN外网访问内网的操作步骤

    外网访问内网SVN 需要将路由映射到VisualSVN server 的443端口 将外网的端口从路由器上进行映射到内网端口,例如将外网的6000端口映射为内网的443端口,443为svn服务器默认端 ...

  5. [笔记] 使用frp从外网访问内网

    之前尝试过otunnel,也记录过使用方法,见[笔记] 使用otunnel从外网访问内网,但是用了几天发现还是不够稳定. 然后尝试frp,发现性能稳定,够用,将过程及配置分享在这里吧. 需求 内网机器 ...

  6. [笔记] 使用otunnel从外网访问内网

    需求 内网机器没有公网IP,但是可以访问外网,现在需要从外网访问内网机器. 举例,在家里机器A访问公司内网机器B. 前提 需要一台有公网IP的服务器S做中转,这样就可以打通AB两端了. A <- ...

  7. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  8. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  9. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

随机推荐

  1. JDK + Tomcat 安装 + 制作自定义镜像【第 1 篇 JDK】

    [第 1 篇 JDK]:https://www.cnblogs.com/del88/p/11842387.html[第 2 篇 Tomcat]:https://www.cnblogs.com/del8 ...

  2. LeetCode:627.交换工资

    题目链接:https://leetcode-cn.com/problems/swap-salary/ 题目 给定一个 salary 表,如下所示,有 m = 男性 和 f = 女性 的值.交换所有的 ...

  3. SAP云平台里Global Account和Sub Account的关系

    在Cloud Foundry环境里,一个Global Account或者Trial Account能够创建多个SubAccount,如图: 创建好的新的subaccount: 一旦subaccount ...

  4. 【转】在 Delphi 中创建 Linux 守护程序(服务进程)

    转自波哥的译文,必须转过来,太有价值了!原文地址在这里.以下为原文内容: 本文译自 原文链接,语言上做了精炼和排版的变更,以便更简洁明了. Delphi 开始支持 Linux 平台为 Delphi 开 ...

  5. jenkins 持续集成笔记2 --- 构建 Java 项目

    先说一下流程: jenkins 从 gitlab pull 代码,使用 maven 打包,然后备份原来的jar包,使用rsync同步到服务器上,重启服务. pipeline 资源去看官方中文文档 ht ...

  6. Matlab[linux]安装问题

    OS : Arch Linux 桌面:Gnome X11 软件是从网上下载的iso文件,对文件挂载或者使用解压软件解压,我个人更喜欢挂载,解压有点麻烦(我比较懒) 软件:matlab(R2016) 开 ...

  7. spring boot2X代码混淆

    为了防止代码很容易被反编译而造成泄露,所以打包时进行代码混淆 使用 proguard-maven-plugin插件 <build> <finalName>${artifactI ...

  8. python_tkinter组件

    1.按钮 # 按钮 # bg设置背景色 btn = tkinter.Button(root,text = '按钮',bg = 'red') btn.pack() # fg设置前景色(文字颜色) btn ...

  9. 老瞎眼 pk 小鲜肉 (线段树)

    链接:https://ac.nowcoder.com/acm/contest/1114/E来源:牛客网 题目描述 老瞎眼有一个长度为 n 的数组 a,为了为难小鲜肉,他准备了 Q 次询问,每次给出 一 ...

  10. java Timer和TimerTask(简单的使用)

    Timer 是一个定时工具 TimerTask 是一个实现了Runnable接口抽象类,代表可以被Timer执行的任务 (1)Timer.schedule(TimerTask task,Date ti ...