Назад | Перейти на главную страницу

Ошибка FTP 500 Illegal Port Command - Команда PORT отправляет IP-адрес, отличный от источника запроса.

Проблема, с которой я столкнулся, заключается в том, что я получаю ответ «500 Illegal PORT command» от FTP-сервера при попытке загрузить файл программным способом.

Эта программа представляет собой небольшое приложение на C #, которое подключается к FTP-сайту и копирует файлы в каталог по умолчанию. Эта программа работает уже несколько лет, и я уверен, что сам код работает нормально. Я также протестировал приложение, подключившись к моему собственному FTP-сайту с помощью того же приложения, и оно работает. Пассивный режим, похоже, не вариант.

При попытке подключиться к FTP-сайту нашего партнера программа работает должным образом, пока не будет выполнена команда FTP put. При запуске Wireshark я заметил, что исходный IP-адрес моего запроса отличается от IP-адреса, отправляемого командой PORT. Я загрузил сюда изображение захвата (вся конфиденциальная информация была удалена с помощью моего удивительный навыки фотошопа):

.

Я связался с владельцем FTP-сайта, на который мы пытаемся передать файлы, и они открыли свой брандмауэр для нашего нового статического IP-адреса. Я могу подключиться к их сайту с помощью FTP-клиентов с компьютеров на обоих IP-адресах LAN, но эти команды PORT всегда отправляются с использованием того же IP-адреса LAN, что и источник запроса. Я также попытался использовать ftp.exe с сервера, на котором находится программа, и это было успешным (но команда PORT использует тот же IP-адрес, что и источник).

Поэтому я предполагаю, что большой вопрос в том, как я могу контролировать, какой IP-адрес использует команда PORT? Или, если я не могу его контролировать, как программа ftp определяет IP-адрес и ПОРТ?

Оказывается, ответ действительно связан с библиотекой FTP, которую я использовал. Я точно думал, что это не проблема кодирования, но после того, как я понюхал, как библиотека создает запрос, я думаю, что нашел ответ.

Вот соответствующий раздел с использованием ILSpy (я поставил пробел вокруг самой важной строки):

private Socket CreateDataSocketActive()
{
    Socket socket = new Socket(2, 1, 6);
    IPHostEntry iPHostEntry = Dns.Resolve(Dns.GetHostName());

    IPEndPoint iPEndPoint = new IPEndPoint(iPHostEntry.get_AddressList()[0], 0);

    socket.Bind(iPEndPoint);
    socket.Listen(5);
    int port = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
    IPAddress address = ((IPEndPoint)socket.get_LocalEndPoint()).get_Address();
    this.SetDataPort((IPEndPoint)socket.get_LocalEndPoint());
    return socket;
}

Похоже, что библиотека создает конечную IP-точку, просто захватывая первый адрес в списке доступных IP-адресов. Для большинства решений это, вероятно, приемлемо, но поскольку на моем сервере несколько сетевых адаптеров, это не работает для меня.

Я знаю, используя FTP.exe, что сервер будет принимать соединения от обеих моих IP-подсетей LAN, если команда PORT выдается с использованием того же IP-адреса LAN, что и источник запроса.

Я предполагаю, что FTP-сервер выполняет какую-то проверку, которая сравнивает два адреса, чтобы убедиться, что они одинаковы. В противном случае я теоретически мог бы передать файл на какое-то другое устройство в совершенно другой сети после входа на FTP-сайт.

Теперь мне нужно найти обходной путь, но это должен быть вопрос поиска новой библиотеки или развертывания моей собственной. Если это поможет кому-то еще, у кого могла быть такая же проблема, я использовал библиотеку com.enterprisedt.net.ftp.