How to connect to FTP via SOCKS5 proxy with Ruby? - ruby

I'm trying to connect to FTP via SOCKS5 proxy using ruby's library Net::FTP. Documentation says to set env variable SOCKS_SERVER in order to connect through proxy (http://ruby-doc.org/stdlib-2.0.0/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-connect), but it seems like it does not work.
Code I'm running is this:
irb(main):054:0> ftp = Net::FTP.new
=> #<Net::FTP:0x007efd08c73768 #mon_owner=nil, #mon_count=0, #mon_mutex=#<Thread::Mutex:0x007efd08c73718>, #binary=true, #passive=true, #debug_mode=false, #resume=false, #sock=#<Net::FTP::NullSocket:0x007efd08c736f0>, #logged_in=false, #open_timeout=nil, #read_timeout=60>
irb(main):056:0> ENV['SOCKS_SERVER'] = 'host:port'
=> "host:port"
irb(main):055:0> ftp.connect('test.rebex.net')
=> nil
irb(main):057:0> ftp.login('demo', 'password')
=> true
irb(main):058:0> ftp.ls
=> ["10-27-15 03:46PM <DIR> pub", "04-08-14 03:09PM 403 readme.txt"]
When I look to proxy logs I can not see any requests going through.
What I'm doing wrong or does anybody have an example how to achieve that?

If your on Windows computer you'll need to use dress_socks gem and Monkeypath:
$socks_server = '127.0.0.1'
$socks_port = '9090'
require 'dress_socks'
class Net::FTP
def open_socket(host, port) # :nodoc:
# puts "opening socket #{#host}:#{port}"
return DressSocks::Socket.new(#host, port,
socks_server: $socks_server, socks_port: $socks_port)
end
end

Related

URI.parse returns nil port for sftp and ftps

When I try to parse the following URLs, URI.parse returns nil for the port:
require 'uri'
url = "ftp://example.com"
puts URI.parse(url).port
# => 21
url = "sftp://example.com"
puts URI.parse(url).port
# => nil
url = "ftps://example.com"
puts URI.parse(url).port
# => nil
Can someone explain why this works for ftp, http and https but not for sftp and ftps?
Because sftp and ftps aren't sepcified, neither the ports they use.
You can check this in the documentation of URI. Look at the namespace.:
http://ruby-doc.org/stdlib-2.1.0/libdoc/uri/rdoc/URI.html
You will find ftp, http, https but no sftp or ftps.
Unrecognized URI's like these will be of type -> URI::Generic
By looking into their documentation you will see that they have a default port of nil.:
http://ruby-doc.org/stdlib-2.1.0/libdoc/uri/rdoc/URI/Generic.html
You can try this out yourself by running this:
puts URI.parse("sftp://example.com").class
They are not supported by default in Ruby -
p URI.scheme_list
#=> {"FTP"=>URI::FTP,
"HTTP"=>URI::HTTP,
"HTTPS"=>URI::HTTPS,
"LDAP"=>URI::LDAP,
"LDAPS"=>URI::LDAPS,
"MAILTO"=>URI::MailTo}
the sftp and ftps are not represented by any Ruby class. Hence, default port for them will not be picked automatically.

Ruby SCGI/XMLRPC client

How is it possible to talk directly to the rtorrent via scgi interface? Ruby's XMLRPC client from stdlib can communicate only over HTTP protocol and rtorrent is only SCGI capable.
as a starter:
#!ruby
require "xmlrpc/client"
class XMLRPC::RTorrent < XMLRPC::Client
def do_rpc(xml, async=false)
headers = {
'CONTENT_LENGTH' => xml.size,
'SCGI' => 1
}
header = "#{headers.to_a.flatten.join("\x00")}"
request = "#{header.size}:#{header},#{xml}"
TCPSocket.open(#host, #port) do |s|
s.write(request)
s.read.split(/\n\s*?\n/, 2)[1]
end
end
end
server = XMLRPC::RTorrent.new("127.0.0.1", '', 5000)
p server.call("system.listMethods")
it ignores async, rtorrent rpc is on port 5000.
more details: http://python.ca/scgi/protocol.txt

How to open secure connection in ruby

I am quite new to ruby here i am opening a secure connection for amazon s3 in ruby.
here i write a simple method as follows when you call this method it establishes a connection but i think it is not as secure
def delete_file(path, &block)
AWS::S3::Base.establish_connection!(:access_key_id => $key, :secret_access_key => $skey) #here propery connection done
AWS::S3::S3Object.delete path, $bkt #here file gets deleted
yield true
end
then i searched and i found start_tls method of eventmachine from
http://eventmachine.rubyforge.org/EventMachine/Connection.html#start_tls-instance_method
You should be able to use :use_ssl => true as written in the manuals:
You can specify whether the url should go over SSL with the
:use_ssl option:
# Url will use https protocol
S3Object.url_for('beluga_baby.jpg', 'marcel', :use_ssl => true)

Connect to a FTPS server with mismatched server certificate using Net::FTPTLS

I am trying to connect via Net::FTPTLS to a Microsoft-based file server (IIS) which is configured to use FTP on port 22 and requires SSL.
I connect via:
require 'net/ftptls'
ftp = Net::FTPTLS.new()
ftp.connect('host.com', port_number)
ftp.login('Username', 'Password')
ftp.puttextfile('somefile.txt', 'where/to/save/somefile.txt')
ftp.close
Problem is, I get the following error:
hostname does not match the server certificate
It seems that I have to disable the openssl peer verification: OpenSSL::SSL::VERIFY_PEER should become OpenSSL::SSL::VERIFY_NONE.
Any ideas on how to monkey-patch the Net::FTPTLS class? Has anyone done this successfully?
Instead using Net::FTPTLS, use Ruby 2.4+ with the following code:
require 'net/ftp'
ftp = Net::FTP.new(nil, ssl: {:verify_mode => OpenSSL::SSL::VERIFY_NONE})
ftp.connect('host.com', port_number)
ftp.login('Username', 'Password')
ftp.puttextfile('somefile.txt', 'where/to/save/somefile.txt')
ftp.close
What I did, rather than monkeypatching ruby itself, was bring a copy of this into /lib of my project.
module Net
class FTPTLS < FTP
def connect(host, port=FTP_PORT)
#hostname = host
super
end
def login(user = "anonymous", params = {:password => nil, :acct => nil, :ignore_cert => false})
store = OpenSSL::X509::Store.new
store.set_default_paths
ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
ctx.cert_store = store
ctx.verify_mode = params[:ignore_cert] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
ctx.key = nil
ctx.cert = nil
voidcmd("AUTH TLS")
#sock = OpenSSL::SSL::SSLSocket.new(#sock, ctx)
#sock.connect
#sock.post_connection_check(#hostname) unless params[:ignore_cert]
super(user, params[:password], params[:acct])
voidcmd("PBSZ 0")
end
end
end
I also cleaned up the param passing a bit. You would use this like so:
require 'ftptls' # Use my local version, not net/ftptls
#ftp_connection = Net::FTPTLS.new()
#ftp_connection.passive = true
#ftp_connection.connect(host, 21)
#ftp_connection.login('user', :password => 'pass', :ignore_cert => true)
HTH
This works fine for me. #ROR
ftp = Net::FTP.new("ftps.host.com", ftp_options)
open("where/is/your/file/somefile.txt") do |file_data|
ftp.putbinaryfile(file_data, 'where/to/save/somefile.txt')
end
ftp.puttextfile('somefile.txt', 'where/to/save/somefile.txt')
def ftp_options
{
port: FTP_PORT,
username: 'ftp_user',
password: 'password',
passive: true,
ssl: { verify_mode: 0 }
}
end
Remember that you have to provide ftps.hostname.com.

Ruby SOAP SSL Woes

I have a SOAP client in Ruby that I'm trying to get working with a Ruby SOAP server, to no avail. The client works fine over SSL with a Python SOAP server, but not with the Ruby version. Here's what the server looks like:
require 'soap/rpc/standaloneServer'
require 'soap/rpc/driver'
require 'rubygems'
require 'httpclient'
def cert(filename)
OpenSSL::X509::Certificate.new(File.open("path to cert.cert") { |f|
f.read
})
end
def key(filename)
OpenSSL::PKey::RSA.new(File.open("path to rsaprivate.key") { |f|
f.read
})
end
class Server < SOAP::RPC::HTTPServer
~code snipped for readability~
end
server = Server.new(:BindAddress => HelperFunctions.local_ip, :Port => 1234, :SSLCertificate => cert("path to cert"), :SSLPrivateKey => key("path to rsa private key"))
new_thread = Thread.new { server.start }
I've trimmed some of the code out for readability's sake (e.g., I have some methods in there I expose) and it works fine with SSL off. But when the client tries to connect, it sees this:
warning: peer certificate won't be verified in this SSL session
/usr/lib/ruby/1.8/net/http.rb:567: warning: using default DH parameters.
/usr/lib/ruby/1.8/net/http.rb:586:in `connect': unknown protocol (OpenSSL::SSL::SSLError)
I tried taking some advice from this post and now I see this message:
/usr/lib/ruby/1.8/soap/httpconfigloader.rb:64:in `set_ssl_config': SSL not supported (NotImplementedError)
Any ideas on how to fix this would be greatly appreciated.
Arg. I was trying to follow along this link and it turns out I was missing a simple include statement:
require 'webrick/https'
That, combined with the help from the link in the original question solves the problem. Hopefully this saves someone else down the line an hour of grief :)
"SSL not supported" can be caused by not having httpclient installed.
Me too.. and don't forget to put the :SSLEnable => true spend couple of hours figuring that out...
server = Server.new(:BindAddress => HelperFunctions.local_ip, :Port => 1234, :SSLEnable => true, :SSLCertificate => cert("path to cert"), :SSLPrivateKey => key("path to rsa private key"))

Resources