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. 我走过的弯路

使用Serv-U搭架FTP服务器很简单,网上教程也很多,不再累述。我这里只记录下我遇到的问题。

3.1. 使用环境

操作系统

FTP软件

FTP软件版本

FTP服务器

Windows XP

Serv-U

版本15.0.1.20

FTP客户端

Windows XP

FileZilla

版本3.8.0

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

3.2. PASV端口范围

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

这就是我遇到的第一个弯路,折腾了很久才知道。虽然数据端口是随机的,但Serv-U可以指定随机的范围。打开Serv-U管理控制台 > 管理服务器 > 服务器限制和设置 > 服务器设置 。在“设置”选项卡里找到“PASV端口范围”,如下图所示,在这里就可以指定随见的范围了。你只要把这些端口映射到路由器就可以了。

图表 1 PASV 端口范围

当然别忘了,还有一个命令端口也得映射。

3.3. PASV IP地址

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

状态:    正在连接 125.89.123.99:13000...

状态:    连接建立,等待欢迎消息...

响应:    220 Serv-U FTP Server v15.0 ready...

命令:    USER zhangsan

响应:    331 User name okay, need password.

命令:    PASS ***

响应:    230 User logged in, proceed.

命令:    CLNT FileZilla

响应:    200 Noted.

命令:    OPTS UTF8 ON

响应:    200 OPTS UTF8 is set to ON.

命令:    OPTS MLST type;size;modify;perm;

响应:    200 MLST OPTS Type;Size;Modify;Perm;

状态:    已连接

状态:    读取目录列表...

命令:    PWD

响应:    257 "/" is current directory.

命令:    TYPE I

响应:    200 Type set to I.

命令:    PASV

响应:    227 Entering Passive Mode (100,100,100,100,50,203)

命令:    MLSD

响应:    150 Opening BINARY mode data connection for MLSD.

错误:    连接超时

错误:    读取目录列表失败

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

4. 总结

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

 

引用: http://blog.csdn.net/benkaoya/article/details/24480411

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

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

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

  2. 外网访问内网Docker容器

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

  3. 外网访问内网SpringBoot

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

  4. 外网访问内网Elasticsearch WEB

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

  5. 怎样从外网访问内网Rails

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

  6. 怎样从外网访问内网Memcached数据库

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

  7. 怎样从外网访问内网CouchDB数据库

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

  8. 怎样从外网访问内网DB2数据库

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

  9. 怎样从外网访问内网OpenLDAP数据库

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

  10. 怎样从外网访问内网Tornado

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

随机推荐

  1. ROW模式的SQL无法正常同步的问题总结

    转自:http://blog.chinaunix.net/uid-20639775-id-4664792.html#_Toc29623 ROW模式的SQL无法正常同步的问题总结 一. 问题起因.... ...

  2. error C2998: 'XXXXXXX' : cannot be a template definition 的可能原因。

    从错误信息的字面意思可以看出来是 XXXXX 不能作为模板定义. 但是为什么不能,并没有说明,最后我翻阅各种资料,各种尝试后,发现往往可能是由于找不到模板函数的某个参数的定义而导致的. templat ...

  3. active mq 配置

    <transportConnectors> <!-- DOS protection, limit concurrent connections to 1000 and frame s ...

  4. FineReport实现java报表多级上报的效果图

    Java报表-上报流程管理 Java报表-上报任务管理 Java报表-我的上报任务 Java报表-系统说明

  5. Mustache(3)

    一.简单示例 代码: 1 function show(t) { 2 $("#content").html(t); 3 } 4 5 var view = { 6 title: 'YZ ...

  6. Unity3D学习笔记——NGUI之UIPopupList

    UIPopupList:将这个组件添加到Button上,即可构建一个下拉列表. 效果图如下: 一:使用步骤 1.首先创建一个Sprite作为button. 2.创建一个label,用于显示当前选择的选 ...

  7. opencv中彩色图转换成灰度图rgb2gray

    imread函数读入图像: 只需要将imread的第二个参数置为0即可. Mat imread(const string& filename, intflags=1 ); 第一个参数是载入图片 ...

  8. day5笔记

    一.上节回顾: 1,find通过元素找索引,可切片,找不到返回-12,index,找不到报错.3,split 由字符串分割成列表,默认按空格.4,captalize 首字母大写,其他字母小写.5,up ...

  9. java输出

    把一个java对象转化成一个json字符串: JSON.toJSON(user); JSON.toJSONStringWithDateFormat(user, "yyyy-MM-dd HH: ...

  10. MySQL的limit子句

    1.理解: limit用来取结果集中的固定几条记录 2.参数: limit offset,pagesize offset:偏移量,为0时,可以省略 pagesize:每页显示的行数,通常是固定的 0表 ...