Total Pageviews

Saturday 15 March 2014

用SSH Config File简化你的生活

If you’re anything like me, you probably log in and out of a half dozen remote servers (or these days, local virtual machines) on a daily basis. And if you’re even more like me, you have trouble remembering all of the various usernames, remote addresses and command line options for things like specifying a non-standard connection port or forwarding local ports to the remote machine.

Shell Aliases

Let’s say that you have a remote server named dev.example.com, which has not been set up with public/private keys for password-less logins. The username to the remote account is fooey, and to reduce the number of scripted login attempts, you’ve decided to change the default SSH port to 2200 from the normal default of 22. This means that a typical command would look like:
$ ssh fooey@dev.example.com -p 22000
password: *************
Not too bad.
We can make things simpler and more secure by using a public/private key pair; I highly recommend using ssh-copy-id for moving your public keys around. It will save you quite a few folder/file permission headaches.
$ ssh fooey@dev.example.com -p 22000
# Assuming your keys are properly setup...
Now this doesn’t seem all that bad. To cut down on the verbosity you could create a simple alias in your shell as well:
$ alias dev='ssh fooey@dev.example.com -p 22000'
$ # To connect:
$ dev
This works surprisingly well: Every new server you need to connect to, just add an alias to your .bashrc (or .zshrc if you hang with the cool kids), and voilà.

~/.ssh/config

However, there’s a much more elegant and flexible solution to this problem. Enter the SSH config file:
# contents of $HOME/.ssh/config
Host dev
    HostName dev.example.com
    Port 22000
    User fooey
This means that I can simply  $ ssh dev, and the options will be read from the configuration file. Easy peasy. Let’s see what else we can do with just a few simple configuration directives.
Personally, I use quite a few public/private keypairs for the various servers and services that I use, to ensure that in the event of having one of my keys compromised the dammage is as restricted as possible. For example, I have a key that I use uniquely for my github account. Let’s set it up so that that particular private key is used for all my github-related operations:
Host dev
    HostName dev.example.com
    Port 22000
    User fooey

Host github.com
    IdentityFile ~/.ssh/github.key
The use of IdentityFile allows me to specify exactly which private key I wish to use for authentification with the given host. You can, of course, simply specify this as a command line option for “normal” connections:
 $ ssh -i ~/.ssh/blah.key username@host.com
but the use of a config file with IdentityFile is pretty much your only option if you want to specify which identity to use for any git commands. This also opens up the very interesting concept of further segmenting your github keys on something like a per-project or per-organization basis:
Host github-project1
    User git
    HostName github.com
    IdentityFile ~/.ssh/github.project1.key

Host github-org
    User git
    HostName github.com
    IdentityFile ~/.ssh/github.org.key

Host github.com
    User git
    IdentityFile ~/.ssh/github.key
Which means that if I want to clone a repository using my organization credentials, I would use the following:
$ git clone git@github-org:orgname/some_repository.git

Going further

As any security-conscious developer would do, I set up firewalls on all of my servers and make them as restrictive as possible; in many cases, this means that the only ports that I leave open are 80/443 (for webservers), and port 22 for SSH (or whatever I might have remapped it to for obfuscation purposes). On the surface, this seems to prevent me from using things like a desktop MySQL GUI client, which expect port 3306 to be open and accessible on the remote server in question. The informed reader will note, however, that a simple local port forward can save you:
$ ssh -f -N -L 9906:127.0.0.1:3306 coolio@database.example.com
# -f puts ssh in background
# -N makes it not execute a remote command
This will forward all local port 9906 traffic to port 3306 on the remote dev.example.com server, letting me point my desktop GUI to localhost (127.0.0.1:9906) and have it behave exactly as if I had exposed port 3306 on the remote server and connected directly to it.
Now I don’t know about you, but remembering that sequence of flags and options for SSH can be a complete pain. Luckily, our config file can help alleviate that:
Host tunnel
    HostName database.example.com
    IdentityFile ~/.ssh/coolio.example.key
    LocalForward 9906 127.0.0.1:3306
    User coolio
Which means I can simply do:
$ ssh -f -N tunnel
And my local port forwarding will be enabled using all of the configuration directives I set up for the tunnel host. Slick.

Homework

There are quite a few configuration options that you can specify in ~/.ssh/config, and I highly suggest consulting the online documentation or the ssh_config man page. Some interesting/useful things that you can do include: change the default number of connection attempts, specify local environment variables to be passed to the remote server upon connection, and even the use of * and ? wildcards for matching hosts.
I hope that some of this is useful to a few of you. Leave a note in the comments if you have any cool tricks for the SSH config file; I’m always on the lookout for fun hacks.

from  http://nerderati.com/2011/03/simplify-your-life-with-an-ssh-config-file/
相关帖子: http://briteming.blogspot.co.uk/2014/02/ssh-config-rubbissh.html
---------------

利用 ssh 的用户配置文件 config 管理 ssh 会话

通常利用 ssh 连接远程服务器,一般都要输入以下类似命令:
1
ssh user@hostname -p port
如果拥有多个 ssh 账号,特别是像我这种喜欢在终端里直接 ssh 登陆,不用 PuTTYSecureCRT 之类的 ssh 客户端的,要记住每个ssh 账号的参数,那是多么蛋疼的事情。
还好,ssh 提供一种优雅且灵活的方式来解决这个问题,就是利用 ssh 的用户配置文件 config 管理 ssh 会话。ssh 的用户配置文件是放在当前用户根目录下的 .ssh 文件夹里(~/.ssh/config,不存在则新创建一个),其配置写法如下:
1
2
3
4
5
Host    别名
    HostName        主机名
    Port            端口
    User            用户名
    IdentityFile    密钥文件的路径
有了这些配置,就可以这样用 ssh 登陆服务器了:
1
ssh 别名
这里以免费的 ssh shell -- CJB 为例,介绍指定密钥文件配置连接 ssh 的用法,如果没有可以在这里注册一个账号。
这 里假设你有一个名为 user 的 CJB ssh 账号,那么用户名就是 "user",端口使用 ssh 默认的端口 "22",CJB 默认使用的主机名是 "shell.cjb.net",不过在镇里这个域名已经被 DNS 污染用不了,只能用 IP 地址 216.194.70.6 代替。
PS:上面的 CJB 主机名 IP 可以通过 dig 获得
1
dig shell.cjb.net
使用密钥的好处就是省去每次 ssh 登陆服务器时都要输入登陆密码的操作,这里使用 ssh-keygen 生成 ssh 密钥(以下操作是在 ~/.ssh/ 目录里执行):
1
ssh-keygen -t rsa
这 里使用 rsa 的加密方式(另外一种加密方式是 dsa),中间会询问密钥生成的位置,这里只输入 cjb,在当前位置生成名为 cjb 的密钥,接着会询问是否要设置一个密码(passphrase),这里留空,直接按回车就行(本来就不想登陆输入密码了...),最后,会在当前目录路径 下生成一个名为 cjb 的私钥,一个名为cjb.pub 的公钥。
把公钥 cjb.pub 上传到远程 cjb 服务器的 ~/.ssh/ 目录下:
1
scp ./cjb.pub user@216.194.70.6:~/.ssh/
上传完后,把公钥 cjb.pub 的内容复制到 authorized_keys 文件里(不存在则新创建一个):
1
cat cjb.pub >> authorized_keys
以 ssh publickey 的形式访问,对当前用户根目录下的 .ssh 文件夹里的目录文件是要有一定的权限要求,之前遇到过 ssh publickey 配置好了,不过用 publickey 登陆验证时则无效。所以,最好设下 .ssh 目录权限为 700,authorized_keys 权限为 600:
1
2
chmod 700 ~/.ssh/
chmod 600 authorized_keys
当 然,用密钥的方式连接服务器是需要服务器上的 ssh 支持的,需要 ssh 的配置文件(默认是在 etc/ssh/sshd_config)里的 PubkeyAuthentication 设置成 yes。如果要改登陆的端口,直接把 Port 改成你想要的端口值就行。修改完后重启下 ssh ,配置就生效:
1
/etc/init.d/ssh restart
还好,CJB 提供的免费 ssh 支持密钥访问。
这样,连接 cjb 的密钥配置完成,本地 ssh 用户配置文件 config 里的 IdentityFile 值写为私钥 cjb 的文件路径 "~/.ssh/cjb" 就行,最后,本地 ssh 用户配置文件 config 的内容如下:
1
2
3
4
5
Host        cjb
    HostName        216.194.70.6
    Port            22
    User            user
    IdentityFile    ~/.ssh/cjb
配置完成后,就可以在终端直接输入 "ssh cjb" 畅通无阻地连上远程的 cjb 服务器上了。
如果有多个 ssh 账号需要配置,在 config 文件里隔行分开写就行,例如:
1
2
3
4
5
6
7
8
9
10
Host        cjb
    HostName        216.194.70.6
    Port            22
    User            user
    IdentityFile    ~/.ssh/cjb
Host        alias
    HostName    hostname
    Port        port
    User        user
嘿嘿,如果你也用 ssh 作 socks5 代理翻墙,以后不用这样写了:
1
ssh -qTfnNC -D 12345 user@216.194.70.6 -p 22
可以省去 user 后面的,直接写成这样:
1
ssh cjb -qTfnNC -D 12345
上面的 scp 传送也可以简写成这样:
1
scp ./cjb.pub cjb:~/.ssh/
执行远程 ssh 命令:
1
ssh cjb "ls ~"
打包一个文件(假设当前目录有个名为 test 的文件夹),接着上传到远程服务器,最后解压文件
1
tar -zcvf - ./test/ | ssh user@216.194.70.6 'cd /user/; tar xvfz -'


socks5代理可以在 .ssh/config 文件中进一步完善配置:
Host cjb
HostName 216.194.70.6
Port 22
User user
IdentityFile ~/.ssh/cjb
DynamicForward 127.0.0.1:12345
这样的话只需要 ssh cjb -qTfnNC就可以了