I've run into a problem in that if I start Emacs in daemon mode on my remote system, then in my local system I run ssh remotehost emacsclient -c, it fails with X11 connection rejected because of wrong authentication. However, things like ssh remotehost xterm work fine, so it's nothing to do with ssh connections, X forwarding, etc.
Both systems in question are running Ubuntu 18.04 LTS.
The problem, as could be guessed, is xauth and in particular after much reading of issues filed back in 2010/2011, it seems to be due to the way GDM sets the XAUTHORITY environment variable to $XDG_RUNTIME_DIR/gdm/Xauthority (something like /run/user/1000/gdm/Xauthority), while incoming SSH connections do not set XAUTHORITY before the set up xauth cookies for the SSH session.
This means that ssh xauth cookies are added in the default $HOME/.Xauthority file. My Emacs daemon cannot see these cookies because it's using the GDM $XDG_RUNTIME_DIR/gdm/Xauthority file.
As I've said it seems like this disparity has been a known issue for 8+ years... has no one resolved it? Crazy. I have written a script that installs the cookie but having to do so is pretty gross.
Is there a way to get my ssh session to use the GDM Xauthority file? I've tried setting XAUTHORITY in my shell setup but apparently that is set too late, after the SSH daemon configures the new Xauth cookie, because it's still put into $HOME/.Xauthority.
It's indeed hard to guess where the X file is. In my case I ended up hacking some shell thing to do it as part of a wrapper around emacsclient. The relevant bits are:
fix_xauth() (
if [[ -z "$XDG_RUNTIME_DIR" ]]; then return; fi
if [[ ! -e "$HOME/.Xauthority" ]]; then return; fi
shopt -s nullglob; shopt -u failglob
for xauth in "$XDG_RUNTIME_DIR/"{".mutter-Xwaylandauth"*,"gdm/Xauthority"}; do
if [[ ! -f "$xauth" ]]; then continue; fi
xauth -f "$xauth" merge "$HOME/.Xauthority"
done
)
Related
I want to establish a stable ssh tunnel between two machines. I have been using autossh for this in the past. However, the present setup does not allow me to perform local port forwarding (this is disabled in sshd_config on both sides for security reasons). As a consequence, it seems that autossh gets confused (it cannot set up a double, local and remote, port forwarding tunnel, to "ping itself", so it seems to be resetting the ssh tunnel periodically). So, I consider instead relying on a "pure ssh" solution, something like:
while true; do
echo "start tunnel..."
ssh -v -o ServerAliveInterval=120 -o ServerAliveCountMax=2 -R remote_port:localhost:local_port user#remote
echo "ssh returned, there was a problem. sleep a bit and retry..."
sleep 15
echo "... ready to retry"
done
My question is: is there some guarantees / stability features that I "used to have" with autossh, but that I will not have with the new solution? Anything I should be aware of? This solution should well check that the server is alive and communicating thanks to the 2 -o options, and restart the tunnel if needed, right?
I' m sure you will find the question similar to many other posts on stackoverflow or on internet. However, I could not find the solution to my problem precisely. I have list of task to be run on remote server, and passing the script is OK! however does not suit to the requirement.
I' m running following from my server to connect to remote server;
ssh -t user#server << 'HERE'
sudo su - <diff_user>
do task as diff_user
HERE
ssh -tt user#server << 'HERE'
sudo su - <diff_user>
do task as diff_user
HERE
With first option (-t), I' m still not able to do sudo, it says below;
sudo: sorry, you must have a tty to run sudo
With second option above (-tt), I' m getting reverse input/output to current server session, total mess.
I tried passing the content as an script to SSH to run on remote host, however, getting similar results.
Is there a way other than commenting out below?
Defaults requiretty in /etc/sudoers file
I have not tried above though, I know RedHat approved it to be removed/ commented out in future version, whenever that is. If I go with step, I will have get above done in 100's of VM's (moreover, I dont have permission to edit the file on VM's and give it a try).
Bug 1020147
Hence, my issue remains the same, as before. It would be great if I can get some input from experts here :)
Addition Info : Using RedHat RHEL 6, 2.6.32-573.3.1
I do have access to the remote host and once I' m in, my ID does not require password to switch to diff_user.
When you are asking this way, I guess you don't have passwordless sudo.
You can't communicate with the remote process (sudo), when you put the script on stdin.
You should rather use the ssh and su command:
ssh -t user#server "sudo su - <diff_user> -c do task as diff_user"
but it might not work. Interactive session can be initiated using expect (a lot of questions around here).
I was trying to connect to another machine in an automated fashion and check some logs only accessible to root/sudo.
This was done by passing the password, server, user, etc. in a file — I know this is not safe and neither a good practice, but this is the way it will be done in my company.
I have several problems:
tcgetattr: Inappropriate ioctl for device;
tty related problems that I don't remember exactly;
sudo: sorry, you must have a tty to run sudo, etc..
Here is the code that worked for me:
#!/bin/bash
function checkLog(){
FILE=$1
readarray -t LINES < "$FILE"
machine=${LINES[4]}
user=${LINES[5]}
password=${LINES[6]}
fileName=${LINES[7]}
numberOfLines=${LINES[8]}
IFS='' read -r -d '' SSH_COMMAND <<EOT
sudo -S <<< '$password' tail $fileName -n $numberOfLines
EOT
RESULTS=$(sshpass -p $password ssh -tt $user#$machine "${SSH_COMMAND}")
echo "$RESULTS"
}
checkLog $1
I'm using flask with apache(mod_wsgi).
When I use ssh module with external command subprocess.call("ssh ......",shell=True)
(My Python Flask code : Not wrong)
ssh = "sshpass -p \""+password+"\" ssh -p 6001 "+username+"#"+servername+" \"mkdir ~/MY_SERVER\""
subprocess.call(ssh, shell=True)
I got this error on Apache error_log : Failed to get a pseudo terminal: Permission denied
How can I fix this?
I've had this problem under RHEL 7. It's due to SELinux blocking apache user to access pty. To solve:
Disable or set SELinux as permissive (check your security needs): edit /etc/selinux/config and reboot.
Allow apache to control its directory for storing SSH keys:
sudo -u apache
chown apache /etc/share/httpd
ssh to desired host, accept key.
I think apache's login shell is "/sbin/nologin".
If you want to allow apache to use shell command, modify /etc/passwd and change the login shell to another shell like "/bin/bash".
However, this method is vulnerable to security. Many python ssh modules are available in internet. Use one of them.
What you are doing seems frightfully insecure. If you cannot use a Python library for your SSH connections, then you should at least plug the hole that is shell=True. There is very little here which is done by the shell anyway; doing it in Python affords you more control, and removes a big number of moving parts.
subprocess.call(['/usr/bin/sshpass', '-p', password,
'/usr/bin/ssh', '-T', '-p', '6001', '{0}#{1}'.format(username, servername),
'mkdir ~/MY_SERVER'])
If you cannot hard-code the paths to sshpass and ssh, you should at least make sure you have a limited, controlled PATH variable in your environment before doing any of this.
The fix for Failed to get a pseudo-terminal is usually to add a -T flag to the ssh command line. I did that above. If your real code actually requires a tty (which mkdir obviously does not), perhaps experiment with -t instead, and/or redirecting standard input and standard output.
I have a problem while trying to use RSYNC with daemon and SSH connection.
What I wan't to do is simply login to rsync without pass and be able to use the rsync daemon.
Here is my conf file (/etc/rsyncd.conf):
uid = rsync
gid = rsync
[yxz]
path = /home/pierre/xyz
read only = false
auth users = rsync
hosts allow = <myIP>
/home/pierre/xyz has gid wich rsync user can reach.
This is working (but is not using the daemon):
rsync -rzP --stats --ignore-existing --remove-sent-files rsync#mydomain.fr:/home/pierre/xyz/ /media/xyz --include="*.cfg" --exclude="*"
This is not working (using the daemon), but rsync asks me for pass and then says "#ERROR: auth failed on module xyz" because I don't have configure authentification this way :
rsync -rzP --stats --ignore-existing --remove-sent-files rsync://rsync#mydomain.fr/xyz/ /media/xyz --include="*.cfg" --exclude="*"
This is not working (using the daemon):
rsync -rzP -e "ssh -l rsync" --stats --ignore-existing --remove-sent-files rsync://rsync#mydomain.fr/xyz/ /media/xyz --include="*.cfg" --exclude="*"
Here is the error message:
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(605) [Receiver=3.0.9]
With -v option to the ssh command, it says connection is allowed, so I suppose rsync is the problem, not ssh.
Any idee ?
Thanks for your help :)
Make sure that you stop and disable the rsync system service. E.g. if you are using systemd: systemctl disable --now rsync.
Remove -l rsync from the rsync command
rsync -rzP -e "ssh" --stats --ignore-existing --remove-sent-files rsync://mydomain.fr/xyz/ /media/xyz --include="*.cfg" --exclude="*"
Remove auth users = rsync from rsyncd.conf
I found that if I was not using root, I had to also add use chroot = no in rsyncd.conf.
Great it works, but what sort of authentification is made ?
The connection is authenticated as usual for the ssh command (specifically, the same as ssh mydomain.fr).
This does not involve the system service rsync. Instead it uses SSH to start and communicate with an instance of rsync --server --daemon .. You can see this command being started if you replace -e "ssh" with -e "ssh -v".
The problem with using the system service rsync is that it does not encrypt the network connection, so the network is able to intercept and modify the data in transit. This somewhat defeats the point of using any authentication.
Often this approach is used with a dedicated SSH key, using the command="" option in authorized_keys to restrict it to rsync only. A side-benefit of doing so is that it overrides the command rsync tries to use, so you can force it to use --config=~/rsyncd.conf instead of creating a global /etc/rsyncd.conf. IMO this is useful to avoid confusion IMO. It is good practice because if you create the global config file, there is some risk that you will accidentally run the insecure system service. For example Debian 9 enables the rsync system service by default, and will start it automatically at boot if you have created /etc/rsyncd.conf.
https://gist.github.com/trendels/6582e95012f6c7fc6542
https://indico.cern.ch/event/577279/contributions/2354037/attachments/1366772/2071442/Hepsysman-keeping-in-sync.pdf
https://serverfault.com/questions/6367/cant-get-rsync-to-work-in-daemon-over-ssh-mode
Unusual variant using a dedicated user with a custom shell, instead of command="" / ForceCommand, for some reason: http://mennucc1.debian.net/howto-ssh-rsyncd.html
To use rsync daemon without a password, you should remove auth users line from your config file.
uid = rsync
gid = rsync
[yxz]
path = /home/pierre/xyz
read only = false
hosts allow = <myIP>
After starting the daemon, you can refer the module either using :: syntax or using rsync:// prefix as follows
rsync -rzv rsync#mydomain.fr::xyz/ /media/xyz
rsync -rzv rsync://rsync#mydomain.fr/xyz/ /media/xyz
More info: man rsyncd.conf
I am trying to connect to a remote host from my local host through the below command.But there was a setting in the remote host that soon after we login it will prompt to enter a badge ID,password and reason for logging in, because it was coded like that in profile file on remote-host How can I overcome those steps and login directly non-interactively, without disturbing the code in profile.
jsmith#local-host$ ssh -t -t generic_userID#remote-host
Enter your badgeID, < exit > to abort:
Enter your password for <badgeID> :
Enter a one line justification for your interactive login to generic_userID
Small amendment: to overcome remote server expect approach is required, but in case local script connects to bunch of remote servers, which configuration may be broken, just use SSH options:
ssh -f -q -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null USER#TARGETSYSTEM
This will omit ask for password in case there is no ssh_key setup, exit silently and continue with script/other hosts.
Puts ssh to background with -f, which is required when calling ssh command from sh (batch) file to remove local console redirect to remote input (implies -n).
Look into setting up a wrapper script around expect. This should do exactly what you're looking for.
Here are a few examples you can work from.
I have upvoted Marvin Pinto's answer because there is every reason to script this, in case there are other features in the profile that you need, such as Message of the Day motd.
However, there is a quick and dirty alternative if you don't want to make a script and you don't want other features from the profile. Depending on your preferred shell on the remote host, you can insist that the shell bypasses the profile files. For example, if bash is available on the remote host, you can invoke it with:
ssh -t -t generic_userID#remote-host bash --noprofile
I tested the above on the macOS 10.13 version of OpenSSH. Normally the command at the end of the ssh invocation is run non-interactively, but the -t flag allows bash to start an interactive shell.
Details are in the Start-up files section of the Bash Reference Manual.