Using the :ftp module from erlang I am uploading to an FTPS server running vsFTPd with TLS. It is working but it seemed to have reliability issues. To test it I ran
results = 1..1_000 |> Enum.map(&("testing_#{&1}.txt")) |> Enum.map(fn name ->
FileTransfer.Ftps.upload("testing text", name, directory, config)
end) |> Enum.reject(fn res ->
res == :ok
end)
This resulted in a list of 45 elements all containing error: :trans_neg_compl
. I’ve been searching around trying to figure out what this error message means but the closest thing I can find is this https://github.com/yrashk/erlang/blob/master/lib/inets/src/ftp/ftp_response.erl which isn’t very helpful (to me at least).
This is what my FileTransfer.Ftps module looks like (Stripped down but same :ftp module function calls).
defmodule FileTransfer.Ftps do
def upload(content, file_name, dest_dir, config) do
host = to_charlist(config.host)
username = to_charlist(config.user)
password = to_charlist(config.password)
with {:ok, ftp_client} <- :ftp.open(host, tls: []),
:ok <- :ftp.user(ftp_client, username, password) do
file_path = directory |> Path.join(file_name) |> to_charlist()
:ftp.send_bin(ftp_client, file_content, file_path)
:ftp.close(ftp_client)
end
end
end
If anyone could help me figure out what is going on here it would be appreciated. Without knowing where the :trans_neg_compl message is coming from I don’t know where to start looking for the issue.
1 Like
Hmm well that means the first error number was ‘4’, as in ‘4xx’, do you have the full error code number (log it out or so) as that will tell what the full error is? These error are everything from trying to download a file that doesn’t exist, trying to list a directory that doesn’t exist, trying to upload without permission to do so, etc, etc…
2 Likes
Hey, sorry for responding so slowly. Haven’t been feeling great the last couple days. I set the :ftp module to ‘verbose’ in the options
with {:ok, ftp_client} <- :ftp.open(host, tls: [], verbose: true),
:ok <- :ftp.user(ftp_client, username, password) do
file_path = directory |> Path.join(file_name) |> to_charlist()
:ftp.send_bin(ftp_client, file_content, file_path)
:ftp.close(ftp_client)
end
and this is the result (With passwords and other identifying information removed
"Receiving: 220 (vsFTPd 3.0.2)"
"Sending: AUTH TLS"
"Receiving: 234 Proceed with negotiation."
"Sending: PBSZ 0"
"Receiving: 200 PBSZ set to 0."
"Sending: PROT P"
"Receiving: 200 PROT now Private."
"Sending: USER <user_name_here>"
"Receiving: 331 Please specify the password."
"Sending: PASS <password_here>"
"Receiving: 230 Login successful."
"Sending: PASV"
"Receiving: 227 Entering Passive Mode (<ip_part>,<ip_part>,<ip_part>,<ip_part>,4,13)."
"Sending: STOR <my/upload/dir/file_1.txt>"
"Receiving: 425 Security: Bad IP connecting."
I’m going to look into the 425 error an see what I can find. I did a quick google search and there was quite a few results for vsFTPd and getting that error. Thank you for pointing me in the right direction on this.
1 Like
Awesome!
Perfect, yep that 425 is the error. That Bad IP connecting
implies to me that the server has a whitelist of allowed IP’s to transfer from perhaps? Or maybe some intermediary router or proxy is disallowing it?
1 Like
I don’t know if it is the appropriate way of solving it but I found this post https://www.linuxquestions.org/questions/linux-newbie-8/vsftpd-problem-with-425-security-bad-ip-connecting-120158/ which suggested setting ’ pasv_promiscuous=YES’. http://vsftpd.beasts.org/vsftpd_conf.html suggests against that but this is really just for an end to end testing environment I am setting up. The server is hosted on EC2 so it may be because of their load balancer or something pointing it to the IP that is not configured in ’ pasv_address’ or something. Either way, since it is a test environment I think this solves my problem well enough. I really appreciate the help especially since in the end it turned out to not be erlang/elixir related. Thanks again.
1 Like