14

I'd like to copy squid.conf from one server to another.

  • The servers don't talk to each other. I'd like to go through my workstation.
  • Both servers have the file, so it will be overwritten on the target.
  • The files have 600 permission and are owned by root.
  • root login via ssh is disabled (PermitRootLogin no).
  • I'd like to do it in one line, if possible, since it will be a part of a setup guide.

I know to do

ssh source 'tar czpf - -C /etc/squid/ squid.conf' | \
    ssh target 'tar xzpf - -C /etc/squid/'

to copy files between servers and preserve permissions. However, in this case I will get "Permission denied".

I also know I can do this:

ssh -t source 'sudo cat /etc/squid/squid.conf'

This way the -t allows sudo to ask for the admin password before outputing the content of the file.

The problem is, I don't know how to combine those techniques into something that will ask for the sudo password on each server, and transfer the file to its destination. Is this possible?

UPDATE: Here's the best I could come up with:

ssh -t source 'sudo tar czf /tmp/squid.tgz -C /etc/squid squid.conf' && \
ssh source 'cat /tmp/squid.tgz' | \
    ssh target 'cat >/tmp/squid.tgz' && \
ssh -t source 'sudo rm /tmp/squid.tgz' && \
ssh -t target \
    'sudo tar xzf /tmp/squid.tgz -C /etc/squid && sudo rm /tmp/squid.tgz'

Calling this a one-liner seems like a stretch. I think I'll just break it down to separate steps in the setup guide.

itsadok
  • 733

4 Answers4

12

It's easier to chain ssh with ssh than to chain ssh with sudo. So changing the ssh server configuration is ok, I suggest opening up ssh for root of each server, but only from localhost. You can do this with a Match clause in sshd_config:

PermitRootLogin no
Match Host localhost
    PermitRootLogin yes

Then you can set up a key-based authentication chain from remote user to local user and from local user to root. You still have an authentication trail so your logs tell you who logged in as root, and the authentication steps are the same as if sudo was involved.

To connect to a server as root, define an alias in ~/.ssh/config like this:

Host server-root
HostName server.example.com
User root
ProxyCommand "ssh server.example.com nc %h %p"

If you insist on using sudo, I believe you'll need separate commands, as sudo insists on reading from a terminal (even if it has a ticket for your account)¹, and none of the usual file copying methods (scp, sftp, rsync) support interacting with a remote terminal.

Sticking with ssh and sudo, your proposed commands could be simplified. On each side, if you have sudo set up not to ask a password again, you can run it once to get over with the password requirement and another time to copy the file. (You can't easily copy the file directly because the password prompt gets in the way.)

ssh -t source 'sudo true'
ssh -t target 'sudo true'
ssh -t source 'sudo cat squid.conf' |
ssh -t target 'sudo tee /etc/squid/squid.conf'

¹ unless you have NOPASSWD, but then you wouldn't be asking this.

  • The first solution worked well for me but the second line should be Match host localhost. – cduck Aug 29 '17 at 11:10
4

You can set up sudo to not ask password next way:

On source:

user    ALL=NOPASSWD:/bin/cat

On target:

user    ALL=NOPASSWD:/usr/bin/tee

And do on yur machine:

ssh source 'sudo cat /test' | ssh target 'sudo tee /test'

But I recommend to use something like puppet. It's much better and easier solves your problem with config files distribution.

PS. By the way, if you'll set up sudo to ask password from user, the string with [sudo] password for user will apear in target file.

rush
  • 27,403
  • +1 for suggesting puppet, but your solution seems insecure. I might as well allow logging in as root. – itsadok Dec 29 '11 at 14:07
3

Instead of using ssh you can use scp to transfer the file between the servers.

Log into the target server :

Change to the target dir where you want to copy the file.

#scp -r -p -P 22 root@source-ipaddress:/source-path-file-to-copy .

r - recursive p - Preserves modification times, access times, and modes from the original file

Mughil
  • 1,973
2

Without changing ssh configuration, you can create two ssh tunnels host->server1 and server2->host through the ssh connection to server2. Connect these two tunnels on the host machine (same port). And run sudo on server2 to retrieve data from connected tunnels on server1 and save them on server2.

ssh -L60000:${source}:22 -R60000:localhost:60000 -t ${target} 'sudo bash -c "ssh -p 60000 '$(whoami)'@localhost \"cd /path/to/dir; tar -czf - files\"|tar -C/path/to/target -xzf -"'

The idea is: 1- to create a local tunnel from your machine to the source machine on port 60000

ssh -L60000:${source}:22

1b- Create a remote tunnel to reach back to your machine

-R60000:localhost:60000

2- connect to target machine

-t ${target}

3- run all as root on target machine for writing

'sudo bash -c "..."'

4- connect to the source machine through the tunnel. whoami and on localhost meaning the localhost on the ${target} machine.

ssh -p 60000 '$(whoami)'@localhost

5- package the remote file(s) and send it zipped to stdout

cd /path/to/dir; tar -czf - file

6- receive the package through stdout and extract files accordingly on the /path/to/target directory

|tar -C/path/to/target -xzf -

Note: You may receive up to 3 sshkey confirmations and 3 password requests. But files will be copied over.