Ruby Net::SSH multi-hop connection with individual authentication per hop - ruby

I am working on a Ruby script that is running on Host 0.
This host can see Host 1, which itself can see Host 2. But Host 2 can't see Host 0.
Host 0 -> Host 1 -> Host 2
The goal is to establish an SSH connection between Host 0 and Host 2, utilizing Host 1.
My current SSH config file looks like this:
host host1
Hostname host1.net
User user1
host host2
Hostname host2.net
User user2
ProxyCommand ssh host1.net -W %h:%p
The script looks like this:
Net::SSH.start('host2', 'user1',
{:password => 'password1', :timeout => 5, :paranoid => false, :config => './config_file'}) do |ssh|
result = ssh.exec!("hostname")
puts result
end
This works fine for connecting to Host 1. Then this approach begins trying to connect to Host 2, but 'forgets' the paranoid parameter and does not supply a password2. It fails.
How can I make sure that the parameter paranoid and a password2 are passed on for the second SSH hop from Host 1 to Host 2?

I found a solution that works without a config file: The Net-SSH-Gateway project on GitHub (https://github.com/net-ssh/net-ssh-gateway)
It's integration allowed me to authenticate per hop like this:
gateway = Net::SSH::Gateway.new(hop_1["address"], hop_1["user"], {:password => hop_1["pass"], :timeout => 5, :paranoid => false})
gateway.ssh(hop_2["address"], hop_2["user"], {:password => hop_2["pass"], :timeout => 8, :paranoid => false}) do |ssh|
puts ssh.exec!("hostname")
end
gateway.shutdown!

Related

Ruby Datamapper connection with SSL to MariaDB on Amazon RDS

How do I establish a ruby Datamapper connection to MariaDB on Amazon RDS with SSL?
Here's what I did:
A non-SSL connection works when testing with:
uri = 'mysql://user:pass#host:port/db_name'
connection = DataObjects::Connection.new(uri)
=> #<DataObjects::Mysql::Connection:0x000056179a3a5921
connection.secure?
=> false
According to the MySQL datamapper wiki, an ssl connection requires the following options: :ssl_ca, :client_key, and :client_cert.
This would result in the following code:
uri = 'mysql://user:pass#host:port/db_name?'
ssl_opts = 'ssl[ssl_ca]=file&ssl[client_key]=file&ssl[client_cert]=file'
connection = DataObjects::Connection.new(uri + ssl_opts)
connection.secure?
=> false
However the only files get is the RDS combind CA bundle, refered from the RDS docs
I do not have a client_cert at all.
Connecting with the mysql client on cli works with SSL:
mysql --ssl -h host -u user -p pass db_name
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 1638
Server version: 10.1.26-MariaDB MariaDB Server
In doc
https://github.com/datamapper/do/wiki/MySQL
It also says
as tested only ca_cert was required to connect to RDS.
So try adding only ca_cert path and do a test
There's only one parameter required: :ssl => {:ca_cert => 'pem_file'}.
However it looks like using uri string for configuration does not work. The reason is a limitation in Addressable::Uri. It cannot handle query strings which aim to represent hashes with more than 1 level.
The good news is that it works using DataMapper.setup with a config Hash:
DataMapper.setup(:default,
:adapter => 'mysql',
:user => 'user',
:database => 'db_name',
:host => 'host',
:password => 'pass',
:ssl => {
:ca_cert => '/path/to/rds-combined-ca-bundle.pem'
}
)

How to connect to FTP via SOCKS5 proxy with 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

Ruby net/ssh(/multi) nested connections

I'm attempting to use ruby to connect to mongodb. But first I need to connect to the server hosting mongo.
There is a bastion host that is able to be connected to publicly. The database host is only able to be connected to through the bastion.
Here is my code:
require 'net/ssh/gateway'
require 'mongo'
include Mongo
ops_host = '<PUBLIC IP/DNS>'
db_host = '<PRIVATE IP>'
port = '27017'
user = 'ubuntu'
key = File.read("<PATHTOKEY>")
gateway = Net::SSH::Gateway.new( ops_host, user, :key_data => key, :keys_only => TRUE)
gateway.ssh(db_host, user, :key_data => key, :keys_only => TRUE) do |ssh|
puts ssh.exec!("hostname")
client = MongoClient.new(db_host, port)
db = client.db('<DBNAME>')
coll = db.collection('profiles')
puts coll.find().count()
end
I'm able to connect to the database host as the puts ssh.exec!("hostname") command returns the correct hostname, but I cannot get mongo to connect as I keep recieving Failed to connect to a master node errors.

Problem in using NET/TELNET class in ruby

Hii all,
I am telneting a machine using "net/telnet" class that comes in ruby but am having some starnge problem...This is below code i have
require 'net/telnet'
ip="192.168.247.111"
localhost = Net::Telnet::new("Host" =>ip,
"Timeout" => 50,
"Prompt" => /[$%#>] \z/n)
localhost.login("root", "root") { |c| print c }
Now when i run the above code i got en error like
c:/ruby/lib/ruby/1.8/net/telnet.rb:352:in `initialize': getaddrinfo: no address
associated with hostname. (SocketError)
But if i harcoded th Ip address like "Host"=> "192.168.247.111"
am able to make it work means able to telnet to machine...but my requirement it to assign from some variable ....How could i achieve it??
Try this:
require 'net/telnet'
ip="192.168.1.5"
localhost = Net::Telnet::new("Host" => "#{ip}", "Timeout" => 50, "Prompt" => /[$%#>] \z/n)
localhost.login("ziad", "ziad") { |c| print c }

Reject Non-localhost Attempts to Access Webrick

I'm trying to block all non-localhost attempts to access a Webrick process. This is my current code
def do_GET(req, res)
host_name = "localhost:3344".split(":")[0]
if host_name != "localhost" && host_name != "127.0.0.1"
puts "Security alert, accessing through #{host_name}"
return
else
puts "we're fine, #{host_name}"
end
# etc.
Is this easy to break? My thought is that the hostname is hard to spoof to the webserver itself.
Maybe just bind the server to the localhost ip address 127.0.0.1 and then you wont have to worry about non-localhost connections:
s = WEBrick::HTTPServer.new( :Port => 3344, :BindAddress => "127.0.0.1" )
s.start
(the above code is off the top of my head but im sure you get the idea)

Resources