mikejdorm / sftp_ex

MIT License
25 stars 23 forks source link

Error attempting to connect #6

Open janajri opened 7 years ago

janajri commented 7 years ago

Getting follow error when attempting to connect with a password

SftpEx.connect([host: <host>, user: <username>, password: <password> ])

Error: 15:12:53.501 [error] {:error, {:options, {:socket_options, [active: false, failfun: &SftpEx.Helpers.log_ssh_fail_func/3, connectfun: &SftpEx.Helpers.connect_log_func/3]}}} {:error, {:options, {:socket_options, [active: false, failfun: &SftpEx.Helpers.log_ssh_fail_func/3, connectfun: &SftpEx.Helpers.connect_log_func/3]}}}

mikejdorm commented 7 years ago

Thanks. I'm not getting that error when supplying a username/password, and the options your supplying to SftpEx.connect look correct.

When you run iex, what version of Elixir and Erlang/OTP does it display?

It looks like the error is from the Erlang gen_tcp library, and its an issue establishing a socket connection to the sever.

film42 commented 7 years ago

Happening for me as well.

Erlang/OTP 20 
Elixir 1.4.4

I am able to establish a connection with an sftp client just fine. I recently upgraded erlang and elixir.

mikejdorm commented 7 years ago

Thanks @film42. I'm testing out some commands using OTP 20. I did see some possible compatibility issues in the release notes, but so far everything is working fine for me with OTP 20 RC1 and RC2.

Looking at the error message, it may be an issue with the logging functions being passed at connection time. I created a branch that removes these logging functions to see if that's the cause of your issue. Try updating your mix.exs file to use the following dependency and see if that resolves the error.

  defp deps do
    [{:sftp_ex, git: "git://github.com/mikejdorm/sftp_ex.git", branch: "issue6"}]
  end

If that doesn't work try running the following commands in erl. I'm curious whether calling Erlang directly will give you a good connection.

  ssh:start().
  ssh_sftp:start_channel("YOUR_HOSTNAME", 22, [{user, "YOUR_USERNAME"}, {password, 
 "YOUR_PASSWORD"}, {user_interaction, false}, {silently_accept_hosts, true}]).
film42 commented 7 years ago

@mikejdorm I made some progress! I tried your branch which returned

22:12:22.977 [error] {:error, :nxdomain} 

So I realized it's DNS related. If I add the hostname/ip to my /etc/hosts file it works just fine. In my case the sftp server is behind a vpn, although my system can resolve it, just not elixir for some reason.

With the ip/hostname in my /etc/hosts file, I attempted to acess through erl and it worked just fine. I removed the line from /etc/hosts and tried elixir again. DNS failed. I tried it in erl again, and in erl it's still working. I restarted my erl process to ensure DNS was not cached or anything. Elixir does not need to be restarted in order to begin failing. As soon as I save my /etc/hosts file with the ip/hostname commented out, it fails in IEX right away.

Diving further I noticed that running the OTP code from elixir results in the same nxdomain error, which is expected at this point...

:ssh.start()
:ssh_sftp.start_channel('HOSTNAME', 22, [{:password,'PASSWORD'}, {:user, 'USER'},
                                         {:user_interaction, false}, {:silently_accept_hosts, true}])
{:error, :nxdomain}

However, :inet_res.lookup('HOSTNAME', :in, :a) correctly resolves the ip just fine in both elixir and erlang.

Although after diving through some OTP code, it looks like we end up right here: https://github.com/erlang/otp/blob/cdc5545536ddeedf9ae4db20464afa6565f4327d/lib/kernel/src/inet.erl#L1229 .. in other words, we never use inet_res. I mean, the easy solution here is to bypass dns resolution in the ssh lib and do it myself:

[ip] = :inet_res.lookup('HOSTNAME', :in, :a)
:ssh_sftp.start_channel(ip, 22, [{:password,'PASSWORD'}, {:user, 'USERNAME'},
                                 {:user_interaction, false}, {:silently_accept_hosts, true}])  
{:ok, #PID<0.1408.0>, #PID<0.1406.0>}

And finally, I just wanted to sanity check myself here. I tested a different server that has a public dns, not behind a firewall that requires a vpn tunnel and it connects just fine. So it's looking more and more like this is an user issue and not a lib issue. Cleaning up the errors messages helped me see that.

Not sure this stream of consciousness is helpful, but I learned a lot! :)

mikejdorm commented 7 years ago

@film42 That's really helpful! I'll look into adding some better handling within the connection code. I could add the inet_res.lookup call as part of SftpEx.connect process. I'll need to dig into some of the OTP source first, but I could probably send out a patch in the next day or two. I was able to recreate the issue locally following your instructions - thanks for all the info!

film42 commented 7 years ago

@mikejdorm It used to work just fine, but I'm struggling to find what changed. If this change in behavior is considered normal, then I'm not sure which way to go. It would be nice to have this lib auto-resolve for me, but since this lib is a wrapper around OTP, it might be better to add documentation and let the user manually resolve before connect?

mikejdorm commented 7 years ago

@film42 Got it. I assumed it never worked for you. That makes things interesting. I have a few different versions of OTP installed. I'll test with 19.x vs. 20.0, and see if I can narrow it down.

There are several changes in OTP ssh version4.5 according to the following notes, but I'm not sure what the culprit would be.

http://erlang.org/download/otp_src_20.0-rc1.readme

If adding auto-resolve becomes a big undertaking I'll just doc it for now.

janajri commented 7 years ago

Sorry for my late response but I was able to get the nxdomain error as well but was able to do a manual lookup to resolve the hostname.

dwyd commented 7 years ago

@mikejdorm

Erlang/OTP 20
Elixir 1.5.0

I didn't try on Elixir 1.4.4 but I was receiving the same error as @janajri. Updating to issue6 dep resolved the problem for me. I did not encounter the {:error, :nxdomain} issue like @film42.

# {:sftp_ex, "~> 0.2.1"}

iex(1)> SftpEx.connect([host: 'HOST', port: 22, user: 'USER', password: 'PASSWORD'])
{:error,
 {:options,
  {:socket_options,
   [active: false, failfun: &SftpEx.Helpers.log_ssh_fail_func/3,
    connectfun: &SftpEx.Helpers.connect_log_func/3]}}}
# {:sftp_ex, git: "git://github.com/mikejdorm/sftp_ex.git", branch: "issue6"}

iex(1)> SftpEx.connect([host: 'HOST', port: 22, user: 'USER', password: 'PASSWORD'])
{:ok,
 %SFTP.Connection{channel_pid: #PID<0.000.0>, connection_ref: #PID<0.000.0>,
  host: 'HOST',
  opts: [user: 'USER', password: 'PASSWORD', user_interaction: false,
   silently_accept_hosts: true, rekey_limit: 1000000000000], port: 22}}

Connecting with Erlang commands worked too.

iex(1)> :ssh.start
:ok
iex(2)> :ssh_sftp.start_channel('HOST', [user: 'USER', password: 'PASSWORD'])      
{:ok, #PID<0.000.0>, #PID<0.000.0>}
samrose commented 7 years ago

Experiencing the same error.

# {:sftp_ex, git: "git://github.com/mikejdorm/sftp_ex.git", branch: "issue6"}

...worked for me too

lorantkurthy commented 7 years ago

As I can see in OTP 20 there is no failfun and connectfun option to connect (only for daemon), and the option handling changed in this version:

OTP-12872 Application(s): ssh

           The internal handling of SSH options is re-written.

           Previously there were no checks if a client option was
           given to a daemon or vice versa. This is corrected now.
           If your code has e.g. a client-only option in a call to
           start a daemon, the call will fail.

If I remove these functions in logging_functions, connect works as expected.

jaimeiniesta commented 7 years ago

Hello, I'm also having problems when trying to connect to an SFTP server. I've double checked that I can connect normally from macos FTP, and I've also checked on 2 different SFTP servers.

➔ iex -S mix
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.5.0) - press Ctrl+C to exit (type h() ENTER for help)
iex> host = "... my host here..."
iex> user = "...my user here..."
iex> password = "supers3cret"
iex> {:ok, conn} = SftpEx.connect([host: host, user: user, password: password])
[info] Connected
[error] {:error, {:eoptions, {:password, "supers3cret"}}}
** (MatchError) no match of right hand side value: {:error, {:eoptions, {:password, "supers3cret"}}}

Thanks!

UPDATE: my fault, I was trying to log in a plain FTP server (not SFTP).

kottkrig commented 7 years ago

I was experiencing the same issue. Using the branch issue6 solved it for me.

  defp deps do
    [{:sftp_ex, git: "git://github.com/mikejdorm/sftp_ex.git", branch: "issue6"}]
  end
kottkrig commented 7 years ago

But looking further I realize that the merge of opts and @default_opts is done backwards in issue6 branch. I couldn't specify a custom port.

I made a pull request to issue6 fixing that.

kyleaa commented 6 years ago

Are there any plans to get this merged in (with @kottkrig's fix) and a new version released?

mikejdorm commented 6 years ago

@kyleaa @jjcarstens I merged in the changes and published to hex under release "0.2.5". Everything looks good based on some tests I ran locally.

Apologies for not merging this in earlier. I haven't had time to keep up with this project lately.

jjcarstens commented 6 years ago

Thanks! Just glad you’ve made the library to begin with.

mikejdorm commented 6 years ago

@jjcarstens Thanks for putting together that pull request. I merged in the override options change and tagged it under release 0.2.6. It's available on hex now.