Java Commons Net FTPClient被动主机由于natting而具有错误的ip地址
我正在使用ApacheCommons.NET3.5,并试图从一个(伪装的)NAT盒后面建立一个被动FTPES连接。大IP(F5)。外部FTP服务器不支持 我的问题是无法设置数据通道,因为控制通道返回“进入被动模式(213,43,13,53,27149)”。如果没有EPSV,我在commons.net FTPClient中没有选项忽略返回的ip地址并强制它使用与控制通道相同的ip地址 FTPClient中的方法“\u openDataConnection(String,String)”使用变量“\u被动主机”,该变量由方法“\u parsePassiveModeReply”设置。我想覆盖它,或者强制它保留控制通道的原始ip地址 添加来自Apache Commons Net的代码以供参考 \u org.apache.commons.net.ftp.FTPClient:Java Commons Net FTPClient被动主机由于natting而具有错误的ip地址,java,ssl,nat,apache-commons-net,ftps,Java,Ssl,Nat,Apache Commons Net,Ftps,我正在使用ApacheCommons.NET3.5,并试图从一个(伪装的)NAT盒后面建立一个被动FTPES连接。大IP(F5)。外部FTP服务器不支持 我的问题是无法设置数据通道,因为控制通道返回“进入被动模式(213,43,13,53,27149)”。如果没有EPSV,我在commons.net FTPClient中没有选项忽略返回的ip地址并强制它使用与控制通道相同的ip地址 FTPClient中的方法“\u openDataConnection(String,String)”使用变量“
protected Socket _openDataConnection_(String command, String arg)
throws IOException
{
if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
__dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE) {
return null;
}
final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;
Socket socket;
if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
{
// if no activePortRange was set (correctly) -> getActivePort() = 0
// -> new ServerSocket(0) -> bind to any free local port
ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress());
try {
// Try EPRT only if remote server is over IPv6, if not use PORT,
// because EPRT has no advantage over PORT on IPv4.
// It could even have the disadvantage,
// that EPRT will make the data connection fail, because
// today's intelligent NAT Firewalls are able to
// substitute IP addresses in the PORT command,
// but might not be able to recognize the EPRT command.
if (isInet6Address) {
if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) {
return null;
}
} else {
if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) {
return null;
}
}
if ((__restartOffset > 0) && !restart(__restartOffset)) {
return null;
}
if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
return null;
}
// For now, let's just use the data timeout value for waiting for
// the data connection. It may be desirable to let this be a
// separately configurable value. In any case, we really want
// to allow preventing the accept from blocking indefinitely.
if (__dataTimeout >= 0) {
server.setSoTimeout(__dataTimeout);
}
socket = server.accept();
// Ensure the timeout is set before any commands are issued on the new socket
if (__dataTimeout >= 0) {
socket.setSoTimeout(__dataTimeout);
}
if (__receiveDataSocketBufferSize > 0) {
socket.setReceiveBufferSize(__receiveDataSocketBufferSize);
}
if (__sendDataSocketBufferSize > 0) {
socket.setSendBufferSize(__sendDataSocketBufferSize);
}
} finally {
server.close();
}
}
else
{ // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
// Try EPSV command first on IPv6 - and IPv4 if enabled.
// When using IPv4 with NAT it has the advantage
// to work with more rare configurations.
// E.g. if FTP server has a static PASV address (external network)
// and the client is coming from another internal network.
// In that case the data connection after PASV command would fail,
// while EPSV would make the client succeed by taking just the port.
boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE)
{
_parseExtendedPassiveModeReply(_replyLines.get(0));
}
else
{
if (isInet6Address) {
return null; // Must use EPSV for IPV6
}
// If EPSV failed on IPV4, revert to PASV
if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
return null;
}
_parsePassiveModeReply(_replyLines.get(0));
}
socket = _socketFactory_.createSocket();
if (__receiveDataSocketBufferSize > 0) {
socket.setReceiveBufferSize(__receiveDataSocketBufferSize);
}
if (__sendDataSocketBufferSize > 0) {
socket.setSendBufferSize(__sendDataSocketBufferSize);
}
if (__passiveLocalHost != null) {
socket.bind(new InetSocketAddress(__passiveLocalHost, 0));
}
// For now, let's just use the data timeout value for waiting for
// the data connection. It may be desirable to let this be a
// separately configurable value. In any case, we really want
// to allow preventing the accept from blocking indefinitely.
if (__dataTimeout >= 0) {
socket.setSoTimeout(__dataTimeout);
}
socket.connect(new InetSocketAddress(__passiveHost, __passivePort), connectTimeout);
if ((__restartOffset > 0) && !restart(__restartOffset))
{
socket.close();
return null;
}
if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
{
socket.close();
return null;
}
}
if (__remoteVerificationEnabled && !verifyRemote(socket))
{
socket.close();
throw new IOException(
"Host attempting data connection " + socket.getInetAddress().getHostAddress() +
" is not same as server " + getRemoteAddress().getHostAddress());
}
return socket;
}
protected void _parsePassiveModeReply(String reply)
throws MalformedServerReplyException
{
java.util.regex.Matcher m = __PARMS_PAT.matcher(reply);
if (!m.find()) {
throw new MalformedServerReplyException(
"Could not parse passive host information.\nServer Reply: " + reply);
}
__passiveHost = m.group(1).replace(',', '.'); // Fix up to look like IP address
try
{
int oct1 = Integer.parseInt(m.group(2));
int oct2 = Integer.parseInt(m.group(3));
__passivePort = (oct1 << 8) | oct2;
}
catch (NumberFormatException e)
{
throw new MalformedServerReplyException(
"Could not parse passive port information.\nServer Reply: " + reply);
}
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);
}
}
}
\u org.apache.commons.net.ftp.FTPClient:
protected Socket _openDataConnection_(String command, String arg)
throws IOException
{
if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
__dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE) {
return null;
}
final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;
Socket socket;
if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
{
// if no activePortRange was set (correctly) -> getActivePort() = 0
// -> new ServerSocket(0) -> bind to any free local port
ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress());
try {
// Try EPRT only if remote server is over IPv6, if not use PORT,
// because EPRT has no advantage over PORT on IPv4.
// It could even have the disadvantage,
// that EPRT will make the data connection fail, because
// today's intelligent NAT Firewalls are able to
// substitute IP addresses in the PORT command,
// but might not be able to recognize the EPRT command.
if (isInet6Address) {
if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) {
return null;
}
} else {
if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) {
return null;
}
}
if ((__restartOffset > 0) && !restart(__restartOffset)) {
return null;
}
if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
return null;
}
// For now, let's just use the data timeout value for waiting for
// the data connection. It may be desirable to let this be a
// separately configurable value. In any case, we really want
// to allow preventing the accept from blocking indefinitely.
if (__dataTimeout >= 0) {
server.setSoTimeout(__dataTimeout);
}
socket = server.accept();
// Ensure the timeout is set before any commands are issued on the new socket
if (__dataTimeout >= 0) {
socket.setSoTimeout(__dataTimeout);
}
if (__receiveDataSocketBufferSize > 0) {
socket.setReceiveBufferSize(__receiveDataSocketBufferSize);
}
if (__sendDataSocketBufferSize > 0) {
socket.setSendBufferSize(__sendDataSocketBufferSize);
}
} finally {
server.close();
}
}
else
{ // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
// Try EPSV command first on IPv6 - and IPv4 if enabled.
// When using IPv4 with NAT it has the advantage
// to work with more rare configurations.
// E.g. if FTP server has a static PASV address (external network)
// and the client is coming from another internal network.
// In that case the data connection after PASV command would fail,
// while EPSV would make the client succeed by taking just the port.
boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE)
{
_parseExtendedPassiveModeReply(_replyLines.get(0));
}
else
{
if (isInet6Address) {
return null; // Must use EPSV for IPV6
}
// If EPSV failed on IPV4, revert to PASV
if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
return null;
}
_parsePassiveModeReply(_replyLines.get(0));
}
socket = _socketFactory_.createSocket();
if (__receiveDataSocketBufferSize > 0) {
socket.setReceiveBufferSize(__receiveDataSocketBufferSize);
}
if (__sendDataSocketBufferSize > 0) {
socket.setSendBufferSize(__sendDataSocketBufferSize);
}
if (__passiveLocalHost != null) {
socket.bind(new InetSocketAddress(__passiveLocalHost, 0));
}
// For now, let's just use the data timeout value for waiting for
// the data connection. It may be desirable to let this be a
// separately configurable value. In any case, we really want
// to allow preventing the accept from blocking indefinitely.
if (__dataTimeout >= 0) {
socket.setSoTimeout(__dataTimeout);
}
socket.connect(new InetSocketAddress(__passiveHost, __passivePort), connectTimeout);
if ((__restartOffset > 0) && !restart(__restartOffset))
{
socket.close();
return null;
}
if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
{
socket.close();
return null;
}
}
if (__remoteVerificationEnabled && !verifyRemote(socket))
{
socket.close();
throw new IOException(
"Host attempting data connection " + socket.getInetAddress().getHostAddress() +
" is not same as server " + getRemoteAddress().getHostAddress());
}
return socket;
}
protected void _parsePassiveModeReply(String reply)
throws MalformedServerReplyException
{
java.util.regex.Matcher m = __PARMS_PAT.matcher(reply);
if (!m.find()) {
throw new MalformedServerReplyException(
"Could not parse passive host information.\nServer Reply: " + reply);
}
__passiveHost = m.group(1).replace(',', '.'); // Fix up to look like IP address
try
{
int oct1 = Integer.parseInt(m.group(2));
int oct2 = Integer.parseInt(m.group(3));
__passivePort = (oct1 << 8) | oct2;
}
catch (NumberFormatException e)
{
throw new MalformedServerReplyException(
"Could not parse passive port information.\nServer Reply: " + reply);
}
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);
}
}
}
protectedvoid\u parsePassiveModeReply(字符串回复)
抛出格式错误的ServerReplyException
{
java.util.regex.Matcher m=\u PARMS\u PAT.Matcher(回复);
如果(!m.find()){
抛出新的格式错误的ServerReplyException(
无法分析被动主机信息。\n服务器回复:“+Reply”);
}
__passiveHost=m.group(1).replace(',',');//修复为类似IP地址
尝试
{
intoct1=Integer.parseInt(m.group(2));
intoct2=Integer.parseInt(m.group(3));
__被动端口=(oct1,因为我不能再添加任何链接:其他人对此也有问题: