DaemonForums  

Go Back   DaemonForums > Miscellaneous > Guides

Guides All Guides and HOWTO's.

Reply
 
Thread Tools Display Modes
  #1   (View Single Post)  
Old 2nd September 2022
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 4,128
Default ssh nicknames, local and remote commands in '.ssh/config' or 'ssh_config'

ssh nicknames, local and remote commands in '.ssh/config' or 'ssh_config'

With the following entry in ~/.ssh/config you can shorten the ssh client command to login to the server at 192.168.33.10.
Code:
Host alix
    Hostname 192.168.33.10
    User root
    Port 50022
    PasswordAuthentication no
Instead of
Code:
$ ssh -p 50022 root@parmenides.utp.xnet
you just can type
Code:
$ ssh alix
The ssh_config(5) man page for the the OpenSSH client configuration file describes the keywords that can make your ssh experience simpler:
Code:
ssh(1) obtains configuration data from the following sources in the
following order:

* command-line options
* user's configuration file (~/.ssh/config)
* system-wide configuration file (/etc/ssh/ssh_config)

For each parameter, the first obtained value will be used.  The
configuration files contain sections separated by Host specifications,
and that section is only applied for hosts that match one of the patterns
given in the specification.  The matched host name is usually the one
given on the command line (see the CanonicalizeHostname option for
exceptions).
Do not be discouraged by CanonicalizeHostname. It defaults to 'no' and in our simple use cases it is not needed at all.
The next paragraph explains the order in which these keywords will be used:
Code:
Since the first obtained value for each parameter is used, more host-
specific declarations should be given near the beginning of the file, and
general defaults at the end.
So if nearly all ssh hosts, except 192.168.33.10, use port 61789 and user account 'john', something like this can be used:
Code:
# --- specific config for 'alix'
Host alix
    Hostname 192.168.33.10
    User root
    Port 50022
    PasswordAuthentication no

# --- General defaults for subsequent hosts
Host *
    Port 61789
    User john

# --- first host to use general defaults
Host fbsd
    Hostname 7.22.16.74

# --- second host to use general defaults
Host beta 
    Hostname 5.129.3.143
Now, a $ ssh fbsd will be executed as $ ssh -p 61789 john@7.22.16.74
And $ scp ./monitor.sh fbsd: will run as $ scp -p 61789 john@7.22.16.74:

The ssh_config(5) man page describes these keywords and their arguments:
Code:
The file contains keyword-argument pairs, one per line.  Lines starting
with `#' and empty lines are interpreted as comments. Arguments may
optionally be enclosed in double quotes (") in order to represent
arguments containing spaces. Configuration options may be separated by
whitespace or optional whitespace and exactly one `='; the latter format
is useful to avoid the need to quote whitespace when specifying
configuration options using the ssh, scp, and sftp -o option.

[snip]

(note that keywords are case-insensitive and arguments are case-sensitive)
The descriptions for Host, Hostname, User and Port:
  • Code:
    Host
        Restricts the following declarations (up to the next Host or
        Match keyword) to be only for those hosts that match one of the
        patterns given after the keyword.  If more than one pattern is
        provided, they should be separated by whitespace.  A single `*'
        as a pattern can be used to provide global defaults for all
        hosts. The host is usually the hostname argument given on the
        command line (see the CanonicalizeHostname keyword for
        exceptions).
    
        A pattern entry may be negated by prefixing it with an
        exclamation mark (`!').  If a negated entry is matched, then the
        Host entry is ignored, regardless of whether any other patterns
        on the line match.  Negated matches are therefore useful to
        provide exceptions for wildcard matches.
    
        See PATTERNS for more information on patterns
    Another pattern could be a subnet specification:
    Code:
    Host 10.19.18.*
  • Code:
    Hostname
        Specifies the real host name to log into.  This can be used to
        specify nicknames or abbreviations for hosts.  Arguments to
        Hostname accept the tokens described in the TOKENS section.
        Numeric IP addresses are also permitted (both on the command line
        and in Hostname specifications).  The default is the name given
        on the command line.
  • Code:
    Port
       Specifies the port number to connect on the remote host.  The
       default is 22.
  • Code:
    User
        Specifies the user to log in as.  This can be useful when a
        different user name is used on different machines.  This saves
        the trouble of having to remember to give the user name on the
        command line.

Local commands

Most ssh users know how to execute a command on the remote ssh server. But you also can run a command on the local machine after the ssh connection has been established.
The relevant keywords:
Code:
LocalCommand
    Specifies a command to execute on the local machine after
    successfully connecting to the server.  The command string
    extends to the end of the line, and is executed with the user's
    shell.  Arguments to LocalCommand accept the tokens described in
    the TOKENS section.

    The command is run synchronously and does not have access to the
    session of the ssh(1) that spawned it.  It should not be used for
    interactive commands.

    This directive is ignored unless PermitLocalCommand has been
    enabled.
Code:
PermitLocalCommand
    Allow local command execution via the LocalCommand option or
    using the !command escape sequence in ssh(1).  The argument must
    be yes or no (the default).
An example where after connecting to the 5.129.3.143 remote server, the file auto_install.conf is scp'ed to the server:
Code:
Host beta 
    Hostname 5.129.3.143
    PermitLocalCommand yes
    LocalCommand = scp /home/adriaan/AUTO-install/auto_install.conf %r@%h:AI.CONF
New is that we use the following tokens:
  • %r : the remote username
  • %h : the remote hostname
Instead of '/home/adriaan' we could have used the %d token (local user's home directory).
If administrator Peter would run $ ssh beta that would, instead from '/home/adriaan', scp auto_install.conf from his home directory '/home/peter'.
A shell script that displays all the available tokens, will be presented in the next section.

Remote commands

You will not get a login shell if you specify command(s) to be executed on the server. The ssh session will be terminated after the command(s) have run.
Some well-known ways to specify a remote command:
  • Code:
    ssh usa 'date; env TZ=CET date' 
    Wed Aug 31 19:05:51 EDT 2022
    Thu Sep  1 01:05:51 CEST 2022
    $
  • Code:
    $ echo 'date ; env TZ=CET date' >showdate
    $ ssh usa <showdate
    Pseudo-terminal will not be allocated because stdin is not a terminal.
    Thu Sep  1 01:55:36 EDT 2022
    Thu Sep  1 07:55:36 CEST 2022
    $
  • Code:
    $ ssh alix 'cat  /var/log/daemon' | less
    [snip]
    Aug 31 20:50:36 alix ntpd[7666]: peer 162.159.200.1 now valid
    Aug 31 20:55:18 alix ntpd[7666]: peer 162.159.200.1 now invalid
    Aug 31 21:27:19 alix ntpd[7666]: peer 162.159.200.1 now valid
    $
  • Prefixing a key in the remote server's .ssh/authorized_keys with restrict,command="command".
    Refer to the AUTHORIZED_KEYS FILE FORMAT section in sshd(8) for the details.
    Code:
    $ cat .ssh/authorized_keys    
    restrict,command="date; env TZ=CET date" ecdsa-sha2-nistp256 AAAAE2VjZ ......
    Upon ssh login this will produce:
    Code:
    PTY allocation request failed on channel 0
    Thu Sep  1 19:07:46 EDT 2022
    Fri Sep  2 01:07:46 CEST 2022
    Connection to 4.11.23.234 closed.
    $

An additional method is to specify a command in the Host section with the RemoteCommand keyword:
Code:
RemoteCommand
    Specifies a command to execute on the remote machine after
    successfully connecting to the server.  The command string
    extends to the end of the line, and is executed with the user's
    shell.  Arguments to RemoteCommand accept the tokens described in
    the TOKENS section.
Extending the configuration of the previously mentioned host 'beta' with a RemoteCommand:
Code:
Host beta
    Hostname 5.129.3.143
    PermitLocalCommand yes
    LocalCommand = scp /home/adriaan/AUTO-install/auto_install.conf %r@%h:AI.CONF
    RemoteCommand = doas install -o root -g www -m u=rw,g=r,o= AI.CONF /var/www/MIRROR/auto_install.conf; doas sh -c 'ls -n /var/www/MIRROR >/var/www/MIRROR/index.txt'
The command has to be one single line. Multiple commands have to be separated with ';' but you can not use the '\' continuation character for using a second line.

The first command install(1)s the file AI.CONF with 'root' as user, group www, with permissions 'u=rw,g=r,o=', into the directory /var/www/MIRROR/ as auto_install.conf
Code:
doas install -o root -g www -m u=rw,g=r,o= AI.CONF /var/www/MIRROR/auto_install.conf
The second and last command generates an index.txt for the OpenBSD installer:
Code:
doas sh -c 'ls -n /var/www/MIRROR >/var/www/MIRROR/index.txt'
The .ssh/config
The complete configuration as discussed above:

Code:
# --- specific config for 'alix'
Host alix
    Hostname 192.168.33.10
    User root
    Port 50022

# --- General defaults for subsequent hosts
Host *
    Port 61789
    User john

# --- first host to use general defaults
Host fbsd
    Hostname 7.22.16.74

# --- second host to use general defaults
Host beta 
    Hostname 5.129.3.143
    PermitLocalCommand yes
    LocalCommand = scp /home/adriaan/AUTO-install/auto_install.conf %r@%h:AI.CONF
    RemoteCommand = doas install -o root -g www -m u=rw,g=r,o= AI.CONF /var/www/MIRROR/auto_install.conf; doas sh -c 'ls -n /var/www/MIRROR >/var/www/MIRROR/index.txt'
Feel free to post your (anonymized) tips for using ssh_config(5).
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump
Reply With Quote
  #2   (View Single Post)  
Old 2nd September 2022
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 4,128
Default

Displaying the available tokens for ssh_config(5)

The TOKENS section of ssh_config(5) lists the tokens that can be used in a ssh client configuration file. Not all ssh_config keywords support all tokens. Please refer to this section to find out the details.

Because LocalCommand happens to accept all tokens, we use it to run a script, that displays the names of these tokens, a short description (lifted from the man page) and their values.
Initially I used this LocalCommand line:
Code:
LocalCommand %d/bin/ssh-tokens %C %d %f %H %h %I %i %K %k %L %l %n %p %r %T %t %u
But during execution it aborted with:
Code:
vdollar_percent_expand: unknown key %f
percent_expand: failed
After removing %f the same happened with %H:
Code:
vdollar_percent_expand: unknown key %H
percent_expand: failed
In total this happened for five tokens. The current invocation now skips these five tokens:
Code:
#LocalCommand %d/bin/ssh-tokens %C %d %f %H %h %I %i %K %k %L %l %n %p %r %T %t %u
LocalCommand  %d/bin/ssh-tokens %C %d       %h    %i    %k %L %l %n %p %r %T    %u
All expanded tokens are shown with:
Code:
     21 echo 'The ssh_config(5) tokens passed as parameters are: '
     22 echo $@
The expanded tokens are then assigned to shell variables:
Code:
 24 # Initialize variables, using the token name, but replace the leading '%' by '_' (underscore)
     25
     26   _C=$1; shift
     27   _d=$1; shift
     28 # _f=$1; shift
     29 # _H=$1; shift
     30   _h=$1; shift
     31 # _I=$1; shift
     32   _i=$1; shift
     33 # _K=$1; shift
     34   _k=$1; shift
     35   _L=$1; shift
     36   _l=$1; shift
     37   _n=$1; shift
     38   _p=$1; shift
     39   _r=$1; shift
     40   _T=$1; shift
     41 # _t=$1; shift
     42   _u=$1; shift
Illustration of the impact of shift on the parameters :
Code:
$ cat shifter       
#!/bin/sh

echo Parameters : "$@"

while [ $# -gt 0 ]; do
   echo 'Parameter #1:' $1
   shift
   echo Remaining parameters after 'shift': "$@"
done

$ ./shifter A B C D
Parameters : A B C D
Parameter #1: A
Remaining parameters after shift: B C D
Parameter #1: B
Remaining parameters after shift: C D
Parameter #1: C
Remaining parameters after shift: D
Parameter #1: D
Remaining parameters after shift:
The HERE construct that displays the tokens:
Code:
     44 # By default shell does not throw an error when shell variables do not exist .....
     45 # You can make a shell script abort on a unset variable by using: 'set -o nounset'
     46
     47 cat <<END
     48 ----------------------------------------------------
     49 %% - A literal '%'.
     50 %C - Hash of %l%h%p%r                           : [${_C:-N.A.}]
     51 %d - Local user's home directory                : [${_d:-N.A.}
     52 %f - Fingerprint of the server's host key.      : [${_f:-N.A.}
     53 %H - known_hosts hostname or address that is
     54      being searchedJ for.                       : [${_H:-N.A.}
     55 %h - Remote hostname                            : [${_h:-N.A.}
     56 %I - String describing the reason for a
     57      KnownHostsCommand execution.               : [${_I:-N.A.}
     58 %i - Local user ID                              : [${_i:-N.A.}
     59 %K - Base64 encoded host key.                   : [${_K:-N.A.}
     60 %k - Host key alias if specified, otherwise
     61      the original remote hostname given on the
     62      command line                               : [${_k:-N.A.}
     63 %L - Local hostname                             : [${_L:-N.A.}
     64 %l - Local hostname, including the domain name  : [${_l:-N.A.}
     65 %n - Original remote hostname, as given on the
     66      command line                               : [${_n:-N.A.}
     67 %p - Remote port                                : [${_p:-N.A.}
     68 %r - Remote username                            : [${_r:-N.A.}
     69 %T - Local tun(4) or tap(4) network interface
     70      assigned if tunnel forwarding was
     71      requested, or "NONE" otherwise             : [${_T:-N.A.}
     72 %t - Type of the server host key, e.g.
     73      ssh-ed25519.                               : [${_t:-N.A.}
     74 %u - Local username                             : [${_u:-N.A.}
     75 ----------------------------------------------------
     76 END
Demonstrating the shell variable modifier ':-'
Code:
$ echo $BSD

$ echo ${BSD:-NetBSD}
NetBSD
$ echo $BSD

$ BSD=FreeBSD
$ echo ${BSD:-NetBSD} 
FreeBSD
$ echo $BSD 
FreeBSD
An output sample:
Code:
The ssh_config(5) tokens passed as parameters are: 
1561ebc3b0a26d8fd8d0af7a40680aa2fc404069 /home/adriaan 4.11.23.234 1000 wg-us lenap lenap.utp.xnet dfus 12345 adriaan NONE adriaan
----------------------------------------------------
%% - A literal '%'.
%C - Hash of %l%h%p%r                           : [1561ebc3b0a26d8fd8d0af7a40680aa2fc404069]
%d - Local user's home directory                : [/home/adriaan]
%f - Fingerprint of the server's host key.      : [N.A.]
%H - known_hosts hostname or address that is
     being searchedJ for.                       : [N.A.]
%h - Remote hostname                            : [4.11.23.234]
%I - String describing the reason for a
     KnownHostsCommand execution.               : [N.A.]
%i - Local user ID                              : [1000]
%K - Base64 encoded host key.                   : [N.A.]
%k - Host key alias if specified, otherwise
     the original remote hostname given on the
     command line                               : [wg-us]
%L - Local hostname                             : [lenap]
%l - Local hostname, including the domain name  : [lenap.utp.xnet]
%n - Original remote hostname, as given on the
     command line                               : [wg-us]
%p - Remote port                                : [12345]
%r - Remote username                            : [adriaan]
%T - Local tun(4) or tap(4) network interface
     assigned if tunnel forwarding was
     requested, or "NONE" otherwise             : [NONE]
%t - Type of the server host key, e.g.
     ssh-ed25519.                               : [N.A.]
%u - Local username                             : [adriaan]
----------------------------------------------------
The script has been attached. It only has the ".txt" extension because the forum software insists on attachments having some type of extension. After downloading just rename/'mv' it to 'ssh-tokens' and make it executable with 'chmod u+x'.
Attached Files
File Type: txt ssh-tokens.txt (2.4 KB, 8 views)
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump

Last edited by J65nko; 5th September 2022 at 09:39 PM.
Reply With Quote
  #3   (View Single Post)  
Old 2nd September 2022
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 4,128
Default

Reserved
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump
Reply With Quote
  #4   (View Single Post)  
Old 2nd September 2022
yeti's Avatar
yeti yeti is offline
White-Furred Supervillain
 
Join Date: Jul 2020
Posts: 23
Talking SSH config and Tor

Easy ssh To Onion Addresses

Having a ssh backdoor as tor Hidden Service can save your day. That way you easily can reach e.g. your power-server at home without needing to pierce holes in your router. tor does all the needed magic. I assume you'll find how to define hidden services much faster and written nicer than I could do here in some few minutes.

And check your nc (aka netcat) for the -X and -x option.

Code:
Host *.onion
        VerifyHostKeyDNS no
        ProxyCommand /usr/bin/nc -xlocalhost:9050 -X5 %h %p
But this still would need knowing the long .onion address:

Code:
$ ssh tyt2a445fpyie6ch7pp4fgmssrlr4r3dqpdkgy6hlzqbqbhl63hatadd.onion uptime
 16:31:51 up 28 days, 21:28,  4 users,  load average: 0.60, 0.13, 0.04
Make Onion Addresses Nice Again

Wouldn't something like...
Code:
$ ssh tyt.swarm uptime
 16:34:34 up 28 days, 21:31,  4 users,  load average: 0.31, 0.20, 0.09
...be much nicer?

The following lines do that trick:

Code:
Host tdr.swarm
        Hostname tyt2a445fpyie6ch7pp4fgmssrlr4r3dqpdkgy6hlzqbqbhl63hatadd.onion
Host tyt.swarm
        Hostname tyt2gxaczgele5nwozuqbyjfvlknulmjwnxlogzolu36vyutktxuohad.onion
Host *.swarm
        VerifyHostKeyDNS no
        ProxyCommand /usr/bin/nc -xlocalhost:9050 -X5 %h %p
What's next?

NARF!

Last edited by yeti; 2nd September 2022 at 05:04 PM. Reason: oops... corrected font for -X and -x
Reply With Quote
  #5   (View Single Post)  
Old 8th September 2022
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 4,128
Default

Testing .ssh/config or /etc/ssh_config

To verify and test your configuration you can use the -G option to ssh(1)
Specifying an alternative configuration file with the -F is useful when you want to experiment with a new config without modifying the existing one.
These two ssh(1) options as described in the man page:
Code:
-G  Causes ssh to print its configuration after evaluating Host and
     Match blocks and exit.

-F configfile
     Specifies an alternative per-user configuration file.  If a
     configuration file is given on the command line, the system-wide
     configuration file (/etc/ssh/ssh_config) will be ignored. The
     default for the per-user configuration file is ~/.ssh/config. If
     set to "none", no configuration files will be read.
A test without a config file:
Code:
$ ssh alix -F none -G | less

user adriaan
hostname alix
port 22
addressfamily any
[snip]
passwordauthentication yes
permitlocalcommand no
Using an alternative config file:
Code:
$ cat sshconf-test

Host alix
 Hostname 192.168.33.10
 User root
 Port 22
 PasswordAuthentication no

# --- All hosts use port 12345
Host *
 Port 12345
 PermitLocalCommand yes
 #LocalCommand %d/bin/ssh-tokens %C %d %f %H %h %I %i %K %k %L %l %n %p %r %T %t %u
 LocalCommand  %d/bin/ssh-tokens %C %d       %h    %i    %k %L %l %n %p %r %T    %u

$ ssh -F sshconf-test -G alix | less

user root
hostname 192.168.33.10
port 22
addressfamily any
[snip
passwordauthentication no
permitlocalcommand yes
[snip]
localcommand %d/bin/ssh-tokens %C %d       %h    %i    %k %L %l %n %p %r %T    %u
Specific settings for host 'alix' are now the 'Hostname 192.168.33.10', 'User root', 'Port 22' and 'PasswordAuthentication no'.
Used from the general settings specified under 'Host *' are 'PermitLocalCommand yes' and 'LocalCommand invoking the ssh-tokens script.

Actually I was a little bit surprised that the LocalCommand was enabled for host "alix"
I wrongly assumed that by putting the specific settings for 'alix' at the top of the file, would prevent all subsequent settings under 'Host *' from being applied.
This is true for the 'Port 1234' that does not override the 'Port 22' setting. But for options that are not explicitly set under "Host alix" like "PermitLocalCommand" and "LocalCommand" , the ones from 'Host *' are applicable.

A test with excluding 'alix' with !alix showed that "PermitLocalCommand" was not applied:
Code:
Host * !alix
[snip]
The command:
Code:
$ ssh -F sshconf-test -G alix | egrep -i '(Permit)?LocalCommand'      
permitlocalcommand no
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump
Reply With Quote
  #6   (View Single Post)  
Old 6th November 2022
yeti's Avatar
yeti yeti is offline
White-Furred Supervillain
 
Join Date: Jul 2020
Posts: 23
Default ...and then I wanted to clean up my ssh config a bit...

...and then I wanted to clean up my ssh config a bit...

I wanted to move my *.onion and *.swarm address definitions to an own file which should be an included file of the system wide ssh_config.

So I appended(!) ...
Code:
Include /etc/ssh/ssh_config.d/*.conf
... to /etc/ssh/ssh_config and the tor hosts definitions (as mentioned above) into /etc/ssh/ssh_config.d/tor-onion-and-swarm-hosts.conf and it just did not work.

Using ssh -vvvv sometorhost to dig a bit deeper looked kind of normal except adding (parse only) after mentioning having included my file.

That hint brought me to ...
https://github.com/PowerShell/Win32-...ment-976612862
... which explains:
Quote:
TL;DR
The Include Statement cannot follow a Host or (restrictive) Match directive as it is then used within that directive. To solve this, either put the Include directive to the top of the file or open a new Match block like so:

Code:
Match all
Include config.d/*
# or other locations
So this is a trap specific to the structure of the config file and may happen in many other cases too.

After adding Match all as mentioned there, I finally could enjoy having my host definitions in the system wide ssh_config as cleanly separated own include file. \𝚘/

Last edited by yeti; 6th November 2022 at 07:09 PM. Reason: Unicode monospace --> [FONT="Courier New"]moo![/FONT] && .config --> .conf
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Security X.Org Server New Local Privilege Escalation, Remote Code Execution vulnerabilities J65nko News 1 14th July 2022 01:20 AM
Is there a mistake in SSH_CONFIG(5) for HostbasedAcceptedAlgorithms in OpenBSD 6.9? philomathic_life OpenBSD General 11 25th May 2021 12:33 AM
Where should I put my config? "rc.conf" or "rc.conf.local"? fender0107401 OpenBSD General 2 2nd April 2012 02:53 AM
log from rc.conf.local and rc.local sdesilet OpenBSD General 1 21st January 2010 02:37 AM
Need to use full path to commands and xorg.config problem phreud FreeBSD General 4 17th November 2008 07:44 PM


All times are GMT. The time now is 08:44 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick