Ruby net-ssh wirth proxy command causes freeze - ruby-on-rails

I would like to connect to a remote computer via another using ruby.
This scheme is the following :
Local -> proxy -> remote
I have this code which is doing the work for a direct access :
require 'net/ssh'
Net::SSH.start(remote_host, remote_user) do |ssh|
puts ssh.exec!'hostname'
end
However, when I try with the proxy, the command 'hostname' is executed and correct, but then the code freezes, same if I call ssh.close.
Here is the code :
require 'net/ssh'
require 'net/ssh/proxy/command'
proxy_cmd = Net::SSH::Proxy::Command.new('ssh proxy_user#proxy_host nc %h %p')
Net::SSH.start(remote_host, remote_user, :proxy => proxy) do |ssh|
puts ssh.exec!'hostname'
end
The loggin is done without password thanks to a rsa key. And the proxycommand is working (I was using it in bash before)
Would someone knows what I am doing wrong ?
Thank you very much for your interest,
EDIT : here is the last line in the logs, it blocks there :
I, [2013-10-16T23:01:19.304778 #3785] INFO -- net.ssh.connection.session[4555128]: closing remaining channels (0 open)

I've just bumped in the same issue - command line ssh was working and net/ssh was hanging on me when using proxycommand.
Debuging net/ssh brought me as far as: https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/transport/session.rb#L113 and the whole thing was hanging on the .close call of the socket.
I'm not sure what caused this, but adding timeout to nc command seems to have solved it:
ProxyCommand ssh proxy_server#proxy_server nc -q 1 %h %p

Related

Errno::ENOTTY Inappropriate ioctl for device when connecting to a remote server through Net::SSH on SuSe (with Ruby on Rails 5.2.4)

My Ruby on Rails application remotely starts some scripts on a distant SuSe server (SUSE Linux Enterprise Server 15 SP2). It relies on the net-ssh gem which is declared in the Gemfile: gem 'net-ssh'.
The script is triggerd remotely through the following block:
Net::SSH.start(remote_host, remote_user, password: remote_password) do |ssh|
feed_back = ssh.exec!("#{event.statement}")
end
This works as expected as long as long as the Rails server runs on Windows Server 2016, which is my DEV environment. But when I deploy to the Validation environment, which is SUSE Linux Enterprise Server 15 SP2, I get this error message:
Errno::ENOTTY in myController#myMethod
Inappropriate ioctl for device
On another hand, issuing the SSH request through the command line - from SUSE to SUSE - works as expected too. Reading around I did not find a relevant parameter for the Net::SSH module to solve this.
Your suggestions are welcome!
I finally found out that the message refers to the operating mode of SSH: it requires a sort of terminal emulation - so called pty - wrapped into a SSH chanel.
So I implemented it this way:
Net::SSH.start(remote_host, remote_user, password: remote_password) do |session|
session.open_channel do |channel|
channel.request_pty do |ch, success|
raise "Error requesting pty" unless success
puts "------------ pty successfully obtained"
end
channel.exec "#{#task.statement}" do |ch, success|
abort "could not execute command" unless success
channel.on_data do |ch, data|
puts "------------ got stdout: #{data}"
#task.update_attribute(:return_value, data)
end
channel.on_extended_data do |ch, type, data|
puts "------------ got stderr: #{data}"
end
channel.on_close do |ch|
puts "------------ channel is closing!"
end
end
end
### Wait until the session closes
session.loop
end
This solved my issue.
Note:
The answer proposed above was only a part of the solution. The same error occured again with this source code when deploying to the production server.
The issue appears to be the password to the SSH target: I retyped it by hand instead of doing the usual copy/paste from MS Excel, and the SSH connection is now successful!
As the error raised is not a simple "connection refused", I suspect that the password string had a specific character encoding, or an unexpected ending character.
As the first proposed solution provides a working example, I leave it there.

Ruby XMLRPC localhost Runtime Error : Wrong Size

I am trying to connect to the XMLRPC API of a dokuwiki website.
I am successfully doing that from my own laptop, with a SSL connection, however, when I try to do it from my production server (which hosts both the wiki and the rails app from which the ruby code is executed), I run into a
Runtime Error
Wrong size. Was 163, should be 113
Here's how I initialize the connection :
#wiki = ::XMLRPC::Client.new3(
host: "wiki.example.com",
path: "/lib/exe/xmlrpc.php",
use_ssl: true)
# Temp Hack because SSL Fails
#wiki.instance_variable_get(:#http).instance_variable_set(:#verify_mode, OpenSSL::SSL::VERIFY_NONE)
end
#authenticated = false
authenticate!
end
def authenticate!
# Fails at below line :
#authenticated = #wiki.call("dokuwiki.login", ENV['WIKI_USER'], ENV['WIKI_PASSWORD'])
Rails.logger.info (#authenticated ? "Authenticated on Wiki !" : "Authentication failed on wiki !")
end
I've read many posts saying that there is a bug in the XMLRPC lib of Ruby. I was running ruby 2.1.5pxx on my laptop and ruby 1.9.xx at my server so I did a rvm install 2.1.5, yet the problem is still here
(btw, I assumed it was enough to do a rvm use 2.1.5 and then touch restart to restart my rails server, but how can I check which version of ruby it's using ?)
What is wrong ?
EDIT
On my laptop, I am running ruby 2.1.5p273 (2014-11-13 revision 48405) [x64-mingw32]
On my production server, I am running ruby-2.1.5 [ i686 ]
I tried another library, libxml-xmlrpc, and I get the following error when running the same command:
Net::HTTPBadResponse: wrong status line: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
But again, the same code is running fine with the default ruby xmlrpc client on my Windows + rubyx64 2.1.5, so I really don't get it!
Edit2 : I tried adding
#wiki.http_header_extra = { "accept-encoding" => "identity" }
But then I get a
Authorization failed. HTTP-Error: 401 Unauthorized
The first call #wiki.call("dokuwiki.login", "myUsr", "myPwd") worked, but apparently it failed to authenticate me (Of course I am still using the same login information that should work)
EDIT 3
After investigation, a successful login from any other computer than localhost will set a cookie like
#cookie="DokuWiki=[small string] ; [very big string]
Whereas if I do it on localhost :
I will write [...] for random strings
#cookie="[small string 2]=deleted; DokuWiki=[small string]; [very big string]"
So I have an extra variable info stored in my cookie, which is "[small string 2]=deleted;
I believe this is what makes my authentication fails. Anyone knows what this is ???
So this localhost connection was messing up with the cookie. Apparently, even the ruby library doesn't know why, and the "Wrong size" comes from this unexpected string [random string]=deleted added at the beginning of the cookie.
Unless someone can explain WHY such a string is added, I will accept my solution of simply adding
#wiki.http_header_extra = { "accept-encoding" => "identity" }
which removes the "Wrong size" error, then
if /deleted/.match(#wiki.cookie)
#wiki.cookie = #wiki.cookie.gsub(/.*deleted; /, '')
end
To remove the beginning of the cookie

IMAP Error: Login failed - Roundcube

I'm trying to login to Roundcube only the program won't let me.
I can login to the said account from the shell and mail is setup and working correctly on my server for user 'admin'. It's RC that is the problem. If I check my logs:
/usr/local/www/roundcube/logs/errors
they show:
[21-Sep-2013 17:19:02 +0100]: IMAP Error: Login failed for admin from ip.ip.ip.ip. Could not connect to ip.ip.ip.ip:143:
Connection refused in /usr/local/www/roundcube/program/lib/Roundcube/rcube_imap.php on line 184
(POST /roundcube/?_task=login&_action=login)
which doesn't give me many clues really, just leads me to:
public function connect($host, $user, $pass, $port=143, $use_ssl=null) {}
from
rcube_imap.php
Stuff I've tried, editing:
/usr/local/www/roundcube/config/main.inc.php
with:
// IMAP AUTH type (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or null to use
// best server supported one)
//$rcmail_config['imap_auth_type'] = LOGIN;
$rcmail_config['imap_auth_type'] = null;
// Log IMAP conversation to <log_dir>/imap or to syslog
$rcmail_config['imap_debug'] = /var/log/imap;
With a failed login attempt
/var/log/imap
doesn't even get written to, leaving me no clues. I'm using dovecot and Sendmail on a FreeBSD box with full root access. It's not an incorrect username password combination for sure.
Several Googles on the string 'Roundcube: Connection to storage server failed' are fruitless.
EDIT:
I needed an entry in
/etc/rc.conf
dovecot_enable="YES"
Schoolboy error.
I had the same problem with a letsencrypt certificate and resolve it by disabling peer authentication:
$config['imap_conn_options'] = array(
'ssl' => array('verify_peer' => true, 'verfify_peer_name' => false),
'tls' => array('verify_peer' => true, 'verfify_peer_name' => false),
);
Afterwards you can set the connection string like this (starttls):
$config['default_host'] = 'tls://your-host.tld';
$config['default_port'] = '143';
$config['smtp_server'] = 'tls://your-host.tld';
$config['smtp_port'] = '25';
Or like this (ssl approach):
$config['default_host'] = 'ssl://your-host.tld';
$config['default_port'] = '993';
$config['smtp_server'] = 'ssl://your-host.tld';
$config['smtp_port'] = '587';
Make sure you use the fully qualified hostname of the certificate in the connection string (like your-host.tld) and not an internal hostname (like localhost).
Hope that helps someone else.
Change the maildir to whatever your system uses.
Change Dovecot mail_location setting to
mail_location = maildir:~/Mail
Change Postfix home_mailbox setting to
home_mailbox = Mail/
Restart services and away you go
Taken from this fedoraforum post
If you run fail2ban, then dovecot might get banned following failed Roundcube login attempts. This has happened to me twice already...
First, check if this is indeed the case:
sudo fail2ban-client status dovecot
If you get an output similar to this:
Status for the jail: dovecot
|- Filter
| |- Currently failed: 1
| |- Total failed: 8
| `- File list: /var/log/mail.log
`- Actions
|- Currently banned: 1
|- Total banned: 2
`- Banned IP list: X.X.X.X
i.e. the Currently banned number is higher than 0, then fail2ban was a bit overeager and you have to "unban" dovecot.
Run the fail2ban client in interactive mode:
sudo fail2ban-client -i
and at the fail2ban> prompt enter the following:
set dovecot unbanip X.X.X.X
where X.X.X.X is the IP address of your Dovecot server.
Exit from the interactive client and run sudo fail2ban-client status dovecot again. The Currently banned: field now should have a value of 0. What's more important, RoundCube should work again :-)
The issue is in your mail server.
Check your ports in your mail server and reset it (if necessary):
Port 25 (and 587) must be open for SMTP
Port 143 (and 993) must be open for IMAP
Port 110 must be open for POP3
Also open those ports in your firewall settings.
sudo dovecot should solve the problem.
If not restart dovecot
sudo service dovecot restart

Sendmail working in Linux Terminal, not in Rails 3

I'm running Ubuntu 10.04 with Rails 3.2.2.
I just installed and configured sendmail. When mail is sent through terminal it worked perfectly.
But when i try to call it through Rails, no success.
Although it doesn't really looks like it's failing though. I get no errors, and see this in my console:
#<Mail::Message:40338240, Multipart: false, Headers: <From: alert#email.com>, <To: chris#email.com>, <Subject: Hi chris, a testmail too you!>, <Mime-Version: 1.0>, <Content-Type: text/html>, <importance: High>, <X-Priority: 1>>
I am in development have the following settings in my development.rb:
config.action_mailer.delivery_method = :sendmail
config.action_mailer.sendmail_settings = {
:location => '/usr/sbin/sendmail',
:arguments => '-i -t'
}
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
I have setup an actionmailer, with the corresponding alert_mail.html.erb:
class UserMailer < ActionMailer::Base
default from: "alert#email.com"
def alert_mail(site)
#site = site
#user = site.user
#url = "http://example.com/login"
mail(:to => #user.email_address, :subject => "Hi chris, a testmail too you!", :importance => "High", 'X-Priority' => '1')
end
end
And this is what I call:
UserMailer.alert_mail(site)
Could it be something with permissions?
Things i've tried
- Tried running in production mode
- chmod'd the sendmail executables to 777
- Tried removing the priority settings
- Running it with rails server instead of nginx
I hope someone can help me, thanks in advance!
(email.com is just a replacement, i use a valid domain)
EDIT:
sadiqxs answer does indeed solve the problem when I try to execute the mail function through rails console. But it still doesn't work when it is supposed to, through my browser. Strange thing is, this seems to be happening in nginx only. When I stop nginx, and start rails server, then it works. But when I when nginx is the server, it doesnt send any mail.
I think you need to call
UserMailer.alert_mail(site).deliver
sadiqxs solution is the part of the answer to my question. It fixes the problem that I was calling the function wrong. But it was still not sending email for me. After a while i manage to get it working.
One of the things I found out is that there was actually another mail log which I did oversee:
/var/log/mail.log.1
It showed me the following error:
sendmail[4453]: NOQUEUE: SYSERR(nobody): can not chdir(/var/spool/mqueue-client/): Permission denied
I used ls -ld /var/spool/mqueue-client/ to see that the directory is restricted by the smmsp group:
drwxrws--- 2 smmsp smmsp 4096 2013-01-12 17:51 /var/spool/mqueue-client/
So I added the nobody user (from the error SYSERR(nobody)) to the smmsp group:
usermod -a -G smmsp nobody
I tested again, and it doesn't work yet. After checking the log I got the same error. To be sure I rebooted my server and now the error message changed a little bit:
NOQUEUE: SYSERR(nobody): can not write to queue directory /var/spool/mqueue-client/ (RunAsGid=65534, required=115): Permission denied
After searching and trying useless stuff for a while i decide to change the primary group of nobody to 115 (smmsp) the /etc/psswd file and saw the following settings:
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
to
nobody:x:65534:115:nobody:/nonexistent:/bin/sh
This solved my problem and it's sending mails now. I understand that this is not the best solution, but I don't really know how else I would give nobody access, since it's requiring the specific GID. I hope someone else here does.

How to detect and kill a wedged soffice.bin process?

I'm using libreoffice/openoffice as a headless process to handle some document conversion tasks on my server that I "submit" via unoconv. Once in a while, the process that actually does the work, soffice.bin, seems to get wedged. I tried playing around with strace and saw that when launching new unoconv instances, they still connect and talk to the soffice process, just that nothing else happens after the 'bad' document goes in. If it were so simply as to just detect that soffice does not talk to incoming sockets any more, it'd be easy to write a watchdog. But it's not that simple, apparently. Any ideas how to tell when things have gone south?
Here's what I set up as a cron job:
def monitor_unoconv
retval = false
target_dir = "/tmp/monitor_unoconv"
begin
Timeout::timeout(30) do
FileUtils.mkdir_p(target_dir)
FileUtils.cp(File.dirname(__FILE__) + "/../hello.odt", target_dir)
Dir.chdir target_dir do
retval = system("unoconv -f html hello.odt")
end
end
rescue => e
STDERR.puts "Caught error #{e.inspect}"
retval = false
end
if !retval
STDERR.puts "soffice process appears hung. Killing it"
STDERR.puts `killall soffice.bin`
sleep 5
STDERR.puts `killall -9 soffice.bin`
end
end
Seems to work ok.
Issue might be with soffice mutiple threads,
so resolving trick might be like:
Using unoconv as a service.
creating a init.d script and starting as a daemon.
So instead of unoconv calling soffice to start , unoconv as a service will keep running a single and maintain it.
create starting process file as follows:
!/bin/sh
case "$1" in
    start)
        /usr/bin/unoconv --listener &
        ;;
    stop)
        killall soffice.bin
        ;;
    restart)
        killall soffice.bin
        sleep 1
        /usr/bin/unoconv --listener &
        ;;
esac

Resources