Serv-u 外网访问内网的FTP服务器
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服务器的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
- 怎样从外网访问内网Tornado
外网访问内网Tornado 本地安装了Tornado,只能在局域网内访问,怎样从外网也能访问本地Tornado? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Tornado 默认安装 ...
随机推荐
- flink-connector-kafka consumer的topic分区分配源码
转载请注明原创地址 http://www.cnblogs.com/dongxiao-yang/p/7200599.html flink官方提供了连接kafka的connector实现,由于调试的时候发 ...
- Django学习之raw()方法查询数据
我们经常有这种需求: 用sql来查询以及写入数据到数据库,Django当然也提供了这种方式,那就是通过raw方法: sql = "select * from blog_blog where ...
- c++ why can't class template hide its implementation in cpp file?
类似的问题还有: why can't class template use Handle Class Pattern to hide its implementation? || why there ...
- codeblocks如何watch指针
如果这个指针是指向一个一维数组,那么在watch窗口中右击并选择Dereference,会看到数组的第一个元素 如果这个指针是指向一个struct,那么在watch窗口中右击并选择Dereferenc ...
- objc_runtime使用方法的几个简单例子(转)
1. 给NSObject类动态添加属性h定义部分 [cpp] @interface UIWebView (LoadProgress) @property (nonatomic, assign) NS ...
- Android.mk 输出日志 调试
$(warning "the value of MY_FILES_PATH is $(MY_FILES_PATH)") #jni
- OpenGL ES andoid学习————2
package com.xhm.getaccount; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.F ...
- 七牛上传ipa后自动生成plist文件
1.利用模板技术动态生成plist文件的内容:(模板内容和data替换为plist需要的内容) //artTemplate <script src="js/template.js&qu ...
- C# 如何判断系统是32位还是64位
摘自:http://www.cnblogs.com/tom-tong/archive/2012/03/12/2392173.html public static int GetOSBit() { tr ...
- iframe脸面的页面和父页面之间的交互方法
1.iframe父页面修改iframe中的页面的信息 var obj = document.getElementById("iframeId").contentWindow; ...