Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork156
💻 make your ssh client smarter
License
moul/assh
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Atransparent wrapper that adds support forregex,aliases,gateways,dynamic hostnames,graphviz,json output,yaml configuration, and more toSSH.
lib-ssh wrapsassh as aProxyCommand; it means that it works seamlessly with:
- ssh
- scp
- rsync
- git
- Desktop applications depending on
lib-sshorssh(i.e.,Tower,Atom.io,SSH Tunnel Manager)
For specific examples, see3rd Party Integration
- regex support
- aliases
gate->gate.domain.tld - gateways -> transparent ssh connection chaining
- includes: split configuration in multiple files, note that OpenSSH as of v7.3 hasnative support for this
- local command execution: finally the reverse ofRemoteCommand
- templates: equivalent to host but you can't connect directly to a template, perfect for inheritance
- inheritance: make hosts inherits from host hosts or templates
- variable expansion: resolve variables from the environment
- smart proxycommand: RAW tcp connection when possible with
netcatandsocatas default fallbacks - rate limit: configure a per-host or global rate-limiting
- JSON output
- Graphviz: graphviz reprensentation of the hosts
assh can use theProxyCommand with netcat feature of OpenSSHtransparently and without the pain of using extended configuration.
Connect tohosta usinghostb as a gateway.
flowchart direction TB y[you] a[hosta] b[hostb] fw((firewall)) style fw fill:#f00,color:#fff y ==x fw fw .-> a y --> b b --> a$ssh hosta/hostbuser@hosta $
Equivalent tossh -o ProxyCommand="ssh hostb nc %h %p" hosta
Connect tohosta usinghostb as a gateway usinghostc as a gateway.
flowchart direction TB y[you] a[hosta] b[hostb] c[hostc] fw((firewall)) style fw fill:#f00,color:#fff y ==x fw fw ..-> a y --> c c --> b b --> a$ssh hosta/hostb/hostcuser@hosta $
Equivalent tossh -o ProxyCommand="ssh -o ProxyCommand='ssh hostc nc %h %p' hostb nc %h %p" hosta
You can define an equivalent of the"ProxyCommand with netcat" feature of OpenSSH, with a simpler syntax, more advanced workflows, and a unique fallback feature.
Let's consider the followingassh.yml file
hosts:hosta:Hostname:1.2.3.4hostb:Hostname:5.6.7.8Gateways:hostahostc:Hostname:9.10.11.12Gateways:hostbhostd:Hostname:13.14.15.16GatewayConnectTimeout:2Gateways: -direct -hosta
ssh hosta->ssh 1.2.3.4ssh hostb->ssh -o ProxyCommand="ssh hostb nc %h %p" hostassh hostc->ssh -o ProxyCommand="ssh -o ProxyCommand='ssh hostc nc %h %p' hostb nc %h %p" hostassh hostd->- assh will try to
ssh 13.14.15.16 - then, fallback on
ssh -o ProxyCommand="ssh hostd nc %h %p" hosta - this method allows you to have the best performances when it is possible, but ensure your commands will work if you are outside of your company for instance
- assh will try to
- Automatically regenerates
~/.ssh/configfile when needed - Inspect parent process to determine log level (if you use
ssh -vv,assh will automatically run in debug mode) - Automatically creates
ControlPathdirectories so you can useslashes in yourControlPathoption, can be enabled with theControlMasterMkdir: trueconfiguration in host or globally.
BeforeConnect is called just beforeassh tries to connect to the remote SSH port.
Note:BeforeConnect will be called for each SSH connection; if you use multiple gateways, it will be called for each gateways until one succeed to connect.
Example of Golang template variables:
// Host: http://godoc.org/moul.io/assh/pkg/config/#Host{{.Host.Name}}// localhost{{.Host.HostName}}// 127.0.0.1{{.Host.Port}}// 22{{.Host.User}}// moul{{.Host.Prototype}}// moul@127.0.0.1:22{{.Host}}// {"HostName":"localhost","Port":22","User":"moul","ControlPersist":"yes",...}{{printf"%s:%s" .Host.HostName .Host.Port}}// localhost:22
OnConnect is called as soon as assh is connected to the remote SSH port.
Note:OnConnect is not aware of the authentication process and will always be raised.
Example of Golang template variables:
// Host: http://godoc.org/moul.io/assh/pkg/config/#Host{{.Host.Name}}// localhost{{.Host.HostName}}// 127.0.0.1{{.Host.Port}}// 22{{.Host.User}}// moul{{.Host.Prototype}}// moul@127.0.0.1:22{{.Host}}// {"HostName":"localhost","Port":22","User":"moul","ControlPersist":"yes",...}{{printf"%s:%s" .Host.HostName .Host.Port}}// localhost:22// Stats: http://godoc.org/moul.io/assh/pkg/commands/#ConnectionStats{{.Stats.ConnectedAt}}// 2016-07-20 11:19:23.467900594 +0200 CEST
OnConnectError is called whenassh fails to open a new TCP connection.
Example of Golang template variables:
// Host: http://godoc.org/moul.io/assh/pkg/config/#Host{{.Host.Name}}// localhost{{.Host.HostName}}// 127.0.0.1{{.Host.Port}}// 22{{.Host.User}}// moul{{.Host.Prototype}}// moul@127.0.0.1:22{{.Host}}// {"HostName":"localhost","Port":22","User":"moul","ControlPersist":"yes",...}{{printf"%s:%s" .Host.HostName .Host.Port}}// localhost:22// Error{{.Error}}// dial tcp: lookup localhost: no such host
OnDisconnect is called as the assh socket is closed.
warning: if you don't see a notification when closing an SSH connection, then you probably haveControlMaster configured;OnDisconnect is not linked to thessh program but to itssocket which may stay alive even after exiting thessh program.
Example of Golang template variables:
// Host: http://godoc.org/moul.io/assh/pkg/config/#Host{{.Host.Name}}// localhost{{.Host.HostName}}// 127.0.0.1{{.Host.Port}}// 22{{.Host.User}}// moul{{.Host.Prototype}}// moul@127.0.0.1:22{{.Host}}// {"HostName":"localhost","Port":22","User":"moul","ControlPersist":"yes",...}{{printf"%s:%s" .Host.HostName .Host.Port}}// localhost:22// Stats: http://godoc.org/moul.io/assh/pkg/commands/#ConnectionStats{{.Stats.ConnectedAt}}// 2016-07-20 11:19:23.467900594 +0200 CEST{{.Stats.WrittenBytes}}// 3613{{.Stats.WrittenBytesHuman}}// 3.6kb{{.Stats.DisconnectAt}}// 2016-07-20 11:19:29,520515792 +0200 CEST{{.Stats.ConnectionDuration}}// 6.052615198s{{.Stats.ConnectionDurationHuman}}// 6s{{.Stats.AverageSpeed}}// 596.933bps{{.Stats.AverageSpeedHuman}}// 3.4kb/s
BeforeConfigWrite is called just beforeassh rewrite the~/.ssh/config file.
Example of Golang template variables:
{{.SSHConfigPath}}// ~/.ssh/configExec driver usesGolang's template system to execute a shell command
Usage:exec <binary> [args...]
defaults:Hooks:OnConnect:exec echo '{{.Host}}' | jq .# executes: `echo '{"HostName":"localhost","Port":"22","User":"moul","ControlPersist":"yes",...}' | jq .# which results in printing a pretty JSON of the host# {# "HostName": "localhost",# "Port": "22",# "User": "moul",# "ControlPersist": "yes",# ...# }
defaults:Hooks:OnConnect:exec echo 'New SSH connection to {{.Host.Prototype}}.' | mail -s "SSH connection journal" m+assh@42.am# send an email with the connection prototype
defaults:Hooks:BeforeConfigWrite:exec cp {{.SSHConfigPath}} {{.SSHConfigPath}}.backup# make a copy of ~/.ssh/config before being rewritten
defaults:Hooks:AfterConfigWrite:'exec echo "# date: `date`" >> {{.SSHConfigPath}}'# Append a comment with the compilation date to the generated ~/.ssh/config file
defaults:Hooks:AfterConfigWrite:'exec cat /path/to/my/provider/generated/.ssh/config >> {{.SSHConfigPath}}'# Append another .ssh/config file to the generated .ssh/config file
Theexec commands are blocking, a new driver for background tasks is planned. For now, you can run a job in background like this:
defaults:Hooks:OnConnect: -exec sleep 60 &# execute the `sleep 60` command in background (non-blocking)# if you quit your ssh connection, the process will continue in background.
Write driver usesGolang's template system to write out data to stdout
Usage:write <line:string...>
defaults:Hooks:OnConnect: -write New SSH connection to {{.Host.Prototype}}.# writes: "New SSH connection to moul@127.0.0.1:22." on the terminal on connection
defaults:Hooks:OnDisconnect: -"write SSH connection to {{.Host.Name}} closed, {{ .Stats.WrittenBytes }} bytes written in {{ .Stats.ConnectionDuration }} ({{ .Stats.AverageSpeed }})"# writes: SSH connection to localhost closed, 40 bytes written.
Notify driver usesGolang's template system to open Desktop notifications.
- Mac OS X: Built-in support
- Linux: Depends ongnotifier
- Windows: Not supported
- BSD: Not supported
Usage:notify <line:string...>
defaults:Hooks:OnConnect:notify New SSH connection to {{.Host.Prototype}}.
defaults:Hooks:OnDisconnect: -"notify SSH connection to {{.Host.Name}} closed, {{ .Stats.WrittenBytes }} bytes written in {{ .Stats.ConnectionDuration }} ({{ .Stats.AverageSpeed }})"
assh now manages the~/.ssh/config file, take care to keep a backup your~/.ssh/config file.
~/.ssh/assh.yml is aYAML file containing:
- a
hostsdictionary containing multipleHOST definitions - a
defaultssection containing global flags - and an
includessection containing path to other configuration files
hosts:homer:# ssh homer -> ssh 1.2.3.4 -p 2222 -u robertHostname:1.2.3.4User:robertPort:2222bart:# ssh bart -> ssh 5.6.7.8 -u bart <- direct access# or ssh 5.6.7.8/homer -u bart <- using homer as a gatewayHostname:5.6.7.8User:bartGateways: -direct# tries a direct access first -homer# fallback on homer gatewaymaggie:# ssh maggie -> ssh 5.6.7.8 -u maggie <- direct access# or ssh 5.6.7.8/homer -u maggie <- using homer as a gatewayUser:maggieInherits:bart# inherits rules from "bart"bart-access:# ssh bart-access -> ssh home.simpson.springfield.us -u bartInherits: -bart-template -simpson-templatelisa-access:# ssh lisa-access -> ssh home.simpson.springfield.us -u lisaInherits: -lisa-template -simpson-templatemarvin:# ssh marvin -> ssh marvin -p 23# ssh sad-robot -> ssh sad-robot -p 23# ssh bighead -> ssh bighead -p 23# aliases inherit everything from marvin, except hostnamePort:23Aliases: -sad-robot -bigheaddolphin:# ssh dolphin -> ssh dolphin -p 24# ssh ecco -> ssh dolphin -p 24# same as above, but with fixed hostnamePort:24Hostname:dolphinAliases:eccoRateLimit:10M# 10Mbytes/second rate limitingschooltemplate:User:studentIdentityFile:~/.ssh/school-rsaForwardX11:yesschoolgw:# ssh school -> ssh gw.school.com -l student -o ForwardX11=no -i ~/.ssh/school-rsaHostname:gw.school.comForwardX11:noInherits:schooltemplate"expanded-host[0-7]*":# ssh somehost2042 -> ssh somehost2042.some.zoneHostname:"%h.some.zone"vm-*.school.com:# ssh vm-42.school.com -> ssh vm-42.school.com/gw.school.com -l student -o ForwardX11=yes -i ~/.ssh/school-rsaGateways:schoolgwInherits:schooltemplate# do not automatically create `ControlPath` -> may result in errorControlMasterMkdir:true"*.shortcut1":ResolveCommand:/bin/sh -c "echo %h | sed s/.shortcut1/.my-long-domain-name.com/""*.shortcut2":ResolveCommand:/bin/sh -c "echo $(echo %h | sed s/.shortcut2//).my-other-long-domain-name.com""*.scw":# ssh toto.scw -> 1. dynamically resolves the IP address# 2. ssh {resolved ip address} -u root -p 22 -o UserKnownHostsFile=null -o StrictHostKeyChecking=no# requires github.com/scaleway/scaleway-cliResolveCommand:/bin/sh -c "scw inspect -f {{.PublicAddress.IP}} server:$(echo %h | sed s/.scw//)"User:rootPort:22UserKnownHostsFile:/dev/nullStrictHostKeyChecking:nomy-env-host:User:user-$USERHostname:${HOSTNAME}${HOSTNAME_SUFFIX}templates:# Templates are similar to Hosts; you can inherit from them# but you cannot ssh to a templatebart-template:User:bartlisa-template:User:lisasimpson-template:Host:home.simpson.springfield.usdefaults:# Defaults are applied to each hostsControlMaster:autoControlPath:~/tmp/.ssh/cm/%h-%p-%r.sockControlPersist:yesPort:22User:bobHooks:# Automatically backup ~/.ssh/configBeforeConfigWrite: -'exec set -x; cp {{.SSHConfigPath}} {{.SSHConfigPath}}.bkp'AfterConfigWrite:# Concat another `ssh_config` file with the one just generated by `assh` -'exec cat ~/.ssh/my-heroku-generated-config >> {{.SSHConfigPath}}'# Alert me with a Desktop notification -notify "{{.SSHConfigPath}} has been rewritten"OnConnect:# Log internal information to a file -exec printf '{{.}}' | jq . >> ~/.ssh/last_connected_host.txt# Alert me with a Desktop notification -notify New SSH connection to {{.Host.Prototype}} at {{.Stats.ConnectedAt}}# Write the host prototype to the terminal stderr -write New SSH connection to {{.Host.Prototype}}OnDisconnect:# write on terminal and in a Desktop notification some statistics about the finished connection -"write SSH connection to {{.Host.HostName}} closed, {{.Stats.WrittenBytes }} bytes written in {{.Stats.ConnectionDuration}} ({{.Stats.AverageSpeed}}bps)" -"notify SSH connection to {{.Host.HostName}} closed, {{.Stats.WrittenBytes }} bytes written in {{.Stats.ConnectionDuration}} ({{.Stats.AverageSpeed}}bps)"includes:-~/.ssh/assh.d/*.yml-/etc/assh.yml-$ENV_VAR/blah-blah-*/*.ymlASSHBinaryPath:~/bin/assh# optionally set the path of assh
For further inspiration, theseassh.yml files on public GitHub projects can educate you on how people are using assh
assh usage
NAME: assh - advanced ssh configUSAGE: assh [global options] command [command options] [arguments...]VERSION:2.8.0 (HEAD)AUTHOR(S): Manfred Touron <https://github.com/moul/assh>COMMANDS: ping Send packets to the SSH server and display statistics info Display system-wide information config Manage ssh and assh configuration sockets Manage control sockets help, h Shows a list of commands or help for one commandGLOBAL OPTIONS: --config value, -c value Location of config file (default: "~/.ssh/assh.yml") [$ASSH_CONFIG] --debug, -D Enable debug mode [$ASSH_DEBUG] --verbose, -V Enable verbose mode --help, -h show help --version, -v print the versionRewrites and replaces the existing ~/.ssh/config file.
This action is automatically done by assh when detecting configuration changes.Running this command is useful to set up assh or repair the configuration file.
$assh config build>~/.ssh/configList hosts and options.
$assh config listListing entries *.scw -> root@[hostname_not_specified]:22 StrictHostKeyChecking=no [custom options] UserKnownHostsFile=/dev/null [custom options] *.shortcut1 -> bob@[hostname_not_specified]:22 *.shortcut2 -> bob@[hostname_not_specified]:22 bart -> bart@5.6.7.8:22 bart-access -> bob@[hostname_not_specified]:22 dolphin -> bob@dolphin:24 expanded-host[0-7]* -> bob@%h.some.zone:22 homer -> robert@1.2.3.4:2222 lisa-access -> bob@[hostname_not_specified]:22 maggie -> maggie@[hostname_not_specified]:22 marvin -> bob@[hostname_not_specified]:23 my-env-host -> user-moul@[hostname_not_specified]:22 schoolgw -> bob@gw.school.com:22 ForwardX11=no [custom options] schooltemplate -> student@[hostname_not_specified]:22 ForwardX11=yes [custom options] IdentityFile=~/.ssh/school-rsa [custom options] vm-*.school.com -> bob@[hostname_not_specified]:22 (*) General options: ControlMaster: auto ControlPath: ~/tmp/.ssh/cm/%h-%p-%r.sock ControlPersist: yes Port: 22 User: bob
Generate agraphviz graph of the hosts
$assh config graphviz| dot -Tpng> assh-hosts.pngSearch for<keyword> in hosts and host options.
$assh config search bartListing results for bart: bart -> bart@5.6.7.8:22 bart-access -> moul@[hostname_not_specified]:22
Display system-wide information.
$assh infoDebug mode (client): falseCLI Path: /path/to/asshGo version: go1.6.2OS/Arch: darwin/amd64RC files:- ~/.ssh/assh.yml- ~/.ssh/assh.d/hosts.yml- ~/.ssh/assh.d/moul.yml- ~/.ssh/assh.d/test.ymlStatistics:- 299 hosts- 2 templates- 4 included files
List active control sockets.
$assh sockets list4 active control sockets in "~/.ssh/cm/":- bart/homer/lisa-22-root.sock (14 minutes)- bart/homer-22-root.sock (14 minutes)- bart-22-root.sock (14 minutes)- marge-22-bart.sock (1 hour)
Close active control sockets.
$assh sockets flushClosed 4 control sockets.
Create a master control sockets.
$assh sockets masterSend packets to the SSH server and display stats.
$assh ping -c 4 localhostPING localhost (127.0.0.1) PORT 22 (ssh) PROTO tcpConnected to 127.0.0.1: seq=0 time=321µs protocol=tcp port=22Connected to 127.0.0.1: seq=1 time=501µs protocol=tcp port=22Connected to 127.0.0.1: seq=2 time=550µs protocol=tcp port=22Connected to 127.0.0.1: seq=3 time=641µs protocol=tcp port=22--- localhost assh ping statistics ---4 packets transmitted, 4 packets received, 0.00% packet lossround-trip min/avg/max = 321µs/503.25µs/641µs
Get the latest version using GO (recommended way):
go install moul.io/assh/v2@latest
note: tested with Go1.7 or above
Get the latest released version using homebrew (Mac OS X):
brew install assh
Build the latest version
brew install assh --HEAD
Get a released version on:https://github.com/moul/assh/releases
Install withasdf-vm:
asdf plugin add asshasdf install assh latestasdf global assh latest
To improve experience when using advanced pattern matching, add the following at the end of your.bashrc /.zshrc /config.fish:
alias ssh="assh wrapper ssh --"
This step is notmandatory but highlyrecommended.
Note:ssh does not understand advanced patterns;To bypass this limitation,assh maintains a list ofknown hosts and regenerate the~/.ssh/config with all those expandedknown hosts.
Without the wrapper, the~/.ssh/config risks to be outdated when connecting to a new host for the first time and you will need to launch the command again.
With the wrapper,ssh willalways be called with an updated~/.ssh/config file.
- Backup your old
~/.ssh/config:cp ~/.ssh/config ~/.ssh/config.backup - Create a new
~/.ssh/assh.ymlfile - Run
assh config build > ~/.ssh/configto validate the syntax of your~/.ssh/assh.ymlfile and automatically build your~/.ssh/configfile - You are ready!
assh contains an experimental web application hosted on heroku:https://assh.herokuapp.com/
Convert anassh.yml file tossh_config format:
$http --form POST https://assh-dev.herokuapp.com/assh-to-ssh assh_config=@~/.ssh/assh.d/test.yml| jq -r .ssh_config#This file was automatically generated by assh v2.8.0#on 2018-07-03 21:06:56 +0000 UTC, based on~/.ssh/assh.yml##more info: https://github.com/moul/assh#host-based configurationHost *.scw Port 22 StrictHostKeyChecking no User root UserKnownHostsFile /dev/null # ResolveCommand: /bin/sh -c "scw inspect -f {{.PublicAddress.IP}} server:$(echo %h | sed s/.scw//)"Host lalala Port 22 User moul # HostName: 127.0.0.1Host toto[0-5]toto User samantha#global configurationHost * ProxyCommand assh connect --port=%p %h
Experimental:assh may run in Docker, however you will have limitations:
- The
asshcontainers does not have any binaries exceptassh, you can't useProxyCommand,ResolveCommand... - Docker may run on another host,
ssh localhostwill ssh to Docker host
docker run -it --rm -v ~/.ssh:/.ssh moul/assh --helpassh in Docker is slower and has more limitations, but it may be useful for testing or if you plan to use a Docker host as a remote Gateway
- v1 (2009-2015) - The original implementation. It worked quite well, but was a lot slower, less portable, harder to install for the user and harder to work on to develop new features and fix bugs
assh uses thebuilt-in netcat mode of OpenSSH (shipped with OpenSSH 5.4) by default.If your ssh client doesn't support this feature, you can configure a customProxyCommand configuration, i.e.,
hosts:myserver:host:1.2.3.4gateways:mygateway# configure a custom proxycommandproxycommand:/bin/nc %h %pmygateway:host:5.6.7.8
You can configure this rule globally:
defaults:proxycommand:nc %h %p
Also, be sure to have netcat installed on your system, or use an alternative proxy binary, i.e.,socat.
assh resolves hostnames using the system built-in resolver, depending on the OS, you can enable new features and/or change modules order.
- Linux - nsswitch documentation
- Linux - mDNS support (nss-mdns)
- Mac OS X -
/etc/resolv.confdocumentation
Starting withOpenSSH v6.7 the socket name can be shortened by configuring%C for the name expansion.
defaults:ControlPath:~/tmp/.ssh/cm/%C.sock
%C is a unique identifier based on a hash of the tuple of (local host, remote user, hostname, port).
Each time you callssh,assh will check if the generated~/.ssh/config file is outdated.
By default, it will transparently regenerate the configuration file if needed.
You can disable this behavior by generating the configuration file like this:
assh config build --no-automatic-rewrite
In your ansible.cfg under ssh_connection, make sure you have the following, changing the path to your assh:
[ssh_connection]ansible_ssh_executable = '/usr/local/bin/assh wrapper ssh'- ansible-dotfiles-assh: Ansible - Configure SSH with ASSH
- appflow: Multitenant environment automation
This project exists thanks to all the people who contribute. [Contribute].
Become a financial contributor and help us sustain our community. [Contribute]
Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]
© 2009-2021 Manfred Touron - MIT License
About
💻 make your ssh client smarter
Topics
Resources
License
Code of conduct
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Packages0
Uh oh!
There was an error while loading.Please reload this page.



