36

According to my ssh_config file...

Configuration data is parsed as follows:

  1. command line options
  2. user-specific file
  3. system-wide file

With that said, (and yes, I know, I could scour man ssh_config AND man ssh, and (hope) for documented defaults).. how can I "print out" the active configuration, for ALL current settings. For example, something like...

ssh -o Tunnel=ethernet servername -p 2210 --print-config

SSH-2.0-OpenSSH_7.0
 Command Line Options
   Port 2210
   Host servername
 Command Line Configurations
   Tunnel Ethernet
 Config File
   ...
 SSH Defaults
   ...
   AddressFamily any (???)
   BatchMode no
   ...

This would let you know explicitly exactly what is set, and why. I called out AddressFamily specifically, as it is a perfect example of a configuration option with NO documented default value. From man ssh_config...

Specifies which address family to use when connecting. Valid arguments are any, inet (use IPv4 only), or inet6 (use IPv6 only).

Ugh! Thanks for any constructive suggestions (not just a bunch of RTFM's).

mralexgray
  • 1,213
  • 3
  • 12
  • 29
  • refer to this [post](http://serverfault.com/questions/390488/verify-sshd-configuration). `sshd` uses the config files to override its internal defaults, that are shown in the stock config files after fresh install – gwillie Aug 27 '15 at 03:13
  • 1
    @gwillie Note: `ssh_config` != `sshd_config`. – EEAA Aug 27 '15 at 03:14
  • what does it matter, there's no way to do it, I wrote a script when I had to do it, just make sure you parse the files in the right order – gwillie Aug 27 '15 at 03:19
  • On Mac OS X, only a small subset of the many available options are mentioned in the "stock" config files, unfortunately. – mralexgray Aug 27 '15 at 07:36

2 Answers2

56

There is -G option in recent openssh, which behaves in similar way as -T on server side.

-G Causes ssh to print its configuration after evaluating Host and Match blocks and exit.

By calling ssh -G host you will get options used for connecting to specific host, which can be helpful for debugging conditional matches in ssh_config.

Also setting more verbose log level (-vvv) can help with debugging config parser.

Jakuje
  • 9,145
  • 2
  • 40
  • 44
0

The only potential downside of -G is that it dumps the entire set of variables for a given target host, which is useful for scripting but can be a little messy to visually sort through.

I kludged together a quick-and-dirty AWK script to meet my needs; give it a fragment of a name found on a Host line, and it will print the configuration block as found in the .ssh/config file. Keep in mind that (1) a Host line can have multiple entries on it, and (2) this does assume that configuration lines will be indented for each Host block. Also, the script does not print out any global options specified in the config file, because I didn't want those.

#!/usr/bin/gawk -f
#
# Given a ~/.ssh/config file that looks like
#
#    SettingOne foo
#    SettingTwo bar
#
#    Host hostX hostY
#      SettingBlah yes
#      SettingBlurg no
#
#    Host hostZ
#      SettingBlurg no
#
# then "print_ssh_block hostY" will print out the corresponding Setting block,
# which is considerably easier for a human to read than the output of
# "ssh -G hostY".

BEGIN {
    if (ARGC != 2) {
        print "Usage:  print_ssh_block host_fragment"
        exit 1
    }

    # ARGV[0] is the script file itself
    # ARGV[1] is the string fragment to later match in Host lines; we don't
    # want to actually process it as a filename...
    hostfrag = ARGV[1]
    # ...so we replace it with the filename of SSH's config, which we DO want
    # to process with patterns.
    ARGV[1] = ENVIRON["HOME"] "/.ssh/config"
    ARGC = 2
    inHostBlock = 0
}

/#/ { next }

/^[Hh][Oo][Ss][Tt] / {
    # skip $1, since that's "Host"
    for (i = 2; i <= NF; i++) {
        # $i is the individual host; if it matches the script argument,
        # set or clear the flag appropriately
        inHostBlock = ($i ~ hostfrag) ? 1 : 0
        if (inHostBlock) break
    }
}

# When not in a matching host block, skip the indented lines.
inHostBlock == 0 && /^[[:space:]]/ { next  }

# When inside a matching host block, clear the flag as soon as we reach an
# empty line.
inHostBlock == 1 && /^$/  { inHostBlock = 0 }

# When inside a matching host block, print every line we encounter.
inHostBlock == 1          { print }

There are approximately infinite improvements that could be made to this. True AWK masters can probably write it in about five total lines.

Ti Strga
  • 101
  • 3