Окружающая среда: Я использую Sun Java JDK 1.8.0_60 на 64-разрядной Windows 7, используя Spring Integration 4.1.6 (который, как предполагается, использует Apache Commons Net 3.3 для доступа к FTPS).Как подключиться к серверу FTPS с подключением к данным, используя ту же сессию TLS?
Я пытаюсь интегрировать с нашим приложением автоматическую загрузку с сервера FTPS нашего клиента. Я успешно справился с SFTP-серверами с помощью Spring Integration без каких-либо проблем для других клиентов без проблем, но это первый раз, когда клиент потребовал от нас использовать FTPS, и подключение к нему было очень озадачивающим. Хотя в моем реальном приложении я настраиваю Spring Integration с использованием XML-компонентов, чтобы попытаться понять, что не работает, я использую следующий тестовый код (хотя я анонимирую фактический хост/имя пользователя/пароль здесь):
final DefaultFtpsSessionFactory sessionFactory = new DefaultFtpsSessionFactory();
sessionFactory.setHost("XXXXXXXXX");
sessionFactory.setPort(990);
sessionFactory.setUsername("XXXXXXX");
sessionFactory.setPassword("XXXXXXX");
sessionFactory.setClientMode(2);
sessionFactory.setFileType(2);
sessionFactory.setUseClientMode(true);
sessionFactory.setImplicit(true);
sessionFactory.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
sessionFactory.setProt("P");
sessionFactory.setProtocol("TLSv1.2");
sessionFactory.setProtocols(new String[]{"TLSv1.2"});
sessionFactory.setSessionCreation(true);
sessionFactory.setCipherSuites(new String[]{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"});
final FtpSession session = sessionFactory.getSession();
//try {
final FTPFile[] ftpFiles = session.list("/");
logger.debug("FtpFiles: {}", (Object[]) ftpFiles);
//} catch (Exception ignored) {}
session.close();
Я запускаю этот код с -Djavax.net.debug=all
, чтобы распечатать всю отладочную информацию TLS.
Основное «управляющее» соединение с сервером FTPS прекрасно работает, но когда он пытается открыть соединение для передачи данных (или любое другое соединение, которое я пытался), я получаю javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
, вызванный java.io.EOFException: SSL peer shut down incorrectly
. Если я раскомментировать глотательный-исключения поймать блок вокруг команды session.list
, то я могу увидеть (хотя выход javax.net.debug), что сервер послал следующее сообщение после отказа от соединения для передачи данных SSL рукопожатия:
main, READ: TLSv1.2 Application Data, length = 129
Padded plaintext after DECRYPTION: len = 105
0000: 34 35 30 20 54 4C 53 20 73 65 73 73 69 6F 6E 20 450 TLS session
0010: 6F 66 20 64 61 74 61 20 63 6F 6E 6E 65 63 74 69 of data connecti
0020: 6F 6E 20 68 61 73 20 6E 6F 74 20 72 65 73 75 6D on has not resum
0030: 65 64 20 6F 72 20 74 68 65 20 73 65 73 73 69 6F ed or the sessio
0040: 6E 20 64 6F 65 73 20 6E 6F 74 20 6D 61 74 63 68 n does not match
0050: 20 74 68 65 20 63 6F 6E 74 72 6F 6C 20 63 6F 6E the control con
0060: 6E 65 63 74 69 6F 6E 0D 0A nection..
Что, как представляется, происходит (и это мой первый опыт работы с FTPS, хотя раньше я имел дело с простым FTP) заключается в том, что способ обеспечения подлинности и шифрования сервера как для управления, так и для данных - это то, что после «нормального» TLS-соединение для установления соединения управления и аутентификации происходит там, каждое подключение к данным требует, чтобы клиент подключался к одному сеансу TLS. Для меня это имеет смысл, так как это должно быть работа, но реализация Apache Commons Net FTPS, похоже, не делает этого. Кажется, он пытается установить новый сеанс TLS, и поэтому сервер отклоняет попытку.
На основании this question about resuming SSL sessions in JSSE, похоже, что Java предполагает или требует другого сеанса для каждой комбинации хоста/сообщения. Моя гипотеза заключается в том, что, поскольку соединение данных FTPS находится на другом порте, чем контрольное соединение, оно не находит существующий сеанс и пытается установить новый, поэтому соединение терпит неудачу.
Я вижу три основных возможностей:
- Сервера не ниже стандарта FTPS в требующем тот же сеанс TLS на порт данных, как на порт управления. Я могу подключиться к серверу отлично (используя тот же хост/пользователь/пароль, который я пытаюсь использовать в своем коде) с помощью FileZilla 3.13.1. Сервер идентифицирует себя как «FileZilla Server 0.9.53 beta» при входе в систему, поэтому, возможно, это какой-то проприетарный способ FileZilla делать вещи, и есть что-то странное, что мне нужно сделать, чтобы убедить Java использовать один и тот же сеанс TLS.
- Клиент Apache Commons Net фактически не соответствует стандарту FTPS и разрешает только некоторые подмножества, которые не позволяют обеспечить подключение к данным. Это показалось бы странным, поскольку он, по-видимому, является стандартным способом подключения к FTPS из Java.
- Я полностью что-то пропустил и неправильно разобрал это.
Буду признателен за любое направление, которое вы можете сообщить о том, как подключиться к этому серверу FTPS. Спасибо.
См. эту ссылку для получения более подробной информации https://stackoverflow.com/questions/46631315/when-using-java-apache-ftpclient-for-ftp-tls-getting-remote-host-closed -connect/48616779 # 48616779 –