Jade Dungeon

Linux网络

ssh登录

复制密钥

这个命令组合允许你无密码SSH登录,

ssh-copy-id将密钥复制到远程主机, 并追加到远程账号的~/.ssh/authorized_keys文件中。

复制SSH密钥到目标主机,开启无密码SSH登录。 如果还没有密钥,请使用ssh-keygen命令生成。

ssh-copy-id username@hostname

也可以一步将SSH公钥传输到另一台机器

ssh-keygen; ssh-copy-id user@host; ssh user@host

注意,如果在本地机器的~/.ssh目录下已经有一个SSH密钥对, ssh-keygen命令生成的新密钥可能会覆盖它们,

复制stdin到本地缓冲区

将标准输入(stdin)复制到你的X11缓冲区

你是否使用scp将文件复制到工作用电脑上,以便复制其内容到电子邮件中? xclip可以帮到你,它可以将标准输入复制到X11缓冲区, 你需要做的就是点击鼠标中键粘贴缓冲区中的内容。

ssh user@host cat /path/to/some/file | xclip

压缩与加密

强制使用IPv4,压缩数据流,使用Blowfish加密。

ssh -4 -C -c blowfish-cbc

跳板机登录

通过中间主机建立SSH连接

ssh -t reachable_host ssh unreachable_host

Unreachable_host表示从本地网络无法直接访问的主机, 但可以从reachable_host所在网络访问, 这个命令通过到reachable_host的「隐藏」连接, 创建起到unreachable_host的连接。

连接屏幕

通过SSH连接屏幕 直接连接到远程屏幕会话(节省了无用的父bash进程)。

ssh -t remote_host screen –r

终端复用

人们总是喜欢在一个文本终端中打开许多shell,如果会话突然中断, 或你按下了Ctrl-a d,远程主机上的shell不会受到丝毫影响,你可以重新连接, 其它有用的screen命令有Ctrl-a c(打开新的shell)和Ctrl-a a (在shell之间来回切换),请访问 http://aperiodic.net/screen/quick_reference阅读更多关于screen命令的快速参考。

如果建立一个可以重新连接的远程GNU screen

ssh -t user@some.domain.com /usr/bin/screen –xRR

另一种方式: 打开一个SSH会话后,让其保持永久打开,对于使用笔记本电脑的用户, 如果需要在Wi-Fi热点之间切换,可以保证切换后不会丢失连接。

autossh -M50000 -t server.example.com 'screen -raAd mysession'

持久化连接

创建到目标主机的持久化连接

ssh -MNf @

在后台创建到目标主机的持久化连接,将这个命令和你~/.ssh/config中的配置结合使用:

Host host
ControlPath ~/.ssh/master-%r@%h:%p
ControlMaster no

所有到目标主机的SSH连接都将使用持久化SSH套接字, 如果你使用SSH定期同步文件(使用rsync/sftp/cvs/svn),这个命令将非常有用, 因为每次打开一个SSH连接时不会创建新的套接字。

SSH传输

麦克风

将你的麦克风输出到远程计算机的扬声器 这样来自你麦克风端口的声音将在SSH目标计算机的扬声器端口输出,但遗憾的是,声音质量很差,你会听到很多嘶嘶声。

dd if=/dev/dsp | ssh -c arcfour -C username@host dd of=/dev/dsp

挂载目录

通过SSH挂载目录/文件系统 从http://fuse.sourceforge.net/sshfs.html下载sshfs, 它允许你跨网络安全挂载一个目录。

sshfs name@server:/path/to/folder /path/to/mount/point

比较远程和本地文件

在比较本地文件和远程文件是否有差异时这个命令很管用。

ssh user@host cat /path/to/remotefile | diff /path/to/localfile –

控制带宽

使用cstream控制带宽

tar -cj /backup | cstream -t 777k | ssh host ‘tar -xj -C /backup’

使用bzip压缩文件夹,然后以777k bit/s速率向远程主机传输。 Cstream还有更多的功能,请访问http://www.cons.org/cracauer/cstream.html#usage了解详情,例如:

echo w00t, i’m 733+ | cstream -b1 -t2

断点传输大文件

rsync –partial –progress –rsh=ssh $file_source $user@$host:$destination_file

它可以恢复失败的rsync命令,当你通过VPN传输大文件, 如备份的数据库时这个命令非常有用,需要在两边的主机上安装rsync。

rsync –partial –progress –rsh=ssh $file_source $user@$host:$destination_file local -> remote
# 或
rsync –partial –progress –rsh=ssh $user@$host:$remote_file $destination_file remote -> local

SSH进行网络测试

端口检测

knock  3000 4000 5000 && ssh -p  user@host && knock  5000 4000 3000

在一个端口上敲一下打开某个服务的端口(如SSH),再敲一下关闭该端口, 需要先安装knockd,下面是一个配置文件示例。

[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 3000,4000,5000
seq_timeout = 5
command = /sbin/iptables -A INPUT -i eth0 -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 5000,4000,3000
seq_timeout = 5
command = /sbin/iptables -D INPUT -i eth0 -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn

吞吐量测试

通过SSH连接到主机,显示实时的传输速度,将所有传输数据指向/dev/null,需要先安装pv

# 如果是Debian:
apt-get install pv
# 如果是Fedora:(可能需要启用额外的软件仓库)。
yum install pv
yes | pv | ssh $host "cat > /dev/null"

抓包流量分析

通过SSH W/ WIRESHARK分析流量

ssh root@server.com 'tshark -f "port !22" -w -' | wireshark -k -i –

使用tshark捕捉远程主机上的网络通信,通过SSH连接发送原始pcap数据, 并在wireshark中显示,按下Ctrl+C将停止捕捉,但也会关闭wireshark窗口, 可以传递一个-c #参数给tshark,让它只捕捉#指定的数据包类型, 或通过命名管道重定向数据,而不是直接通过SSH传输给wireshark

我建议你过滤数据包,以节约带宽,tshark可以使用tcpdump替代:

ssh root@example.com tcpdump -w – ‘port !22′ | wireshark -k -i –

SSH代理

从某主机的80端口开启到本地主机2001端口的隧道 现在你可以直接在浏览器中输入http://localhost:2001访问这个网站。

ssh -N -L2001:localhost:80 somemachine

ssh 命令除了登陆外还有三种代理功能:

  • 正向代理(-L):相当于 iptable 的 port forwarding
  • 反向代理(-R):相当于 frp 或者 ngrok
  • socks5 代理(-D):相当于 ss/ssr

如要长期高效的服务,应使用对应的专用软件。如没法安装软件, 比如当你处在限制环境下想要访问下某个不可达到的目标,或者某个临时需求, 那么 ssh 就是你的兜底方案。

正向代理:

所谓「正向代理」就是在本地启动端口,把本地端口数据转发到远端。

用法1:远程端口映射到其他机器

HostB 上启动一个 PortB 端口,映射到HostC:PortC上,在 HostB 上运行:

HostB$ ssh -L 0.0.0.0:PortB:HostC:PortC user@HostC

这时访问HostB:PortB相当于访问HostC:PortC(和 iptable 的 port-forwarding 类似)。

用法2:本地端口通过跳板映射到其他机器

HostA 上启动一个 PortA 端口,通过 HostB 转发到HostC:PortC上,在 HostA 上运行:

HostA$ ssh -L 0.0.0.0:PortA:HostC:PortC  user@HostB

这时访问HostA:PortA相当于访问HostC:PortC

两种用法的区别是,第一种用法本地到跳板机 HostB 的数据是明文的, 而第二种用法一般本地就是 HostA,访问本地的 PortA,数据被 ssh 加密传输给 HostB 又转发给HostC:PortC

反向代理:

所谓「反向代理」就是让远端启动端口,把远端端口数据转发到本地。

HostA 将自己可以访问的HostB:PortB暴露给外网服务器HostC:PortC,在 HostA 上运行:

HostA$ ssh -R HostC:PortC:HostB:PortB  user@HostC

那么链接HostC:PortC就相当于链接HostB:PortB。使用时需修改HostC/etc/ssh/sshd_config,添加:

GatewayPorts yes

相当于内网穿透,比如 HostA 和 HostB 是同一个内网下的两台可以互相访问的机器, HostC是外网跳板机,HostC不能访问 HostA,但是 HostA 可以访问 HostC。

那么通过在内网 HostA 上运行ssh -R告诉 HostC,创建 PortC 端口监听, 把该端口所有数据转发给我(HostA),我会再转发给同一个内网下的HostB:PortB

同内网下的 HostA/HostB 也可以是同一台机器,换句话说就是内网 HostA 把自己可以访问的端口暴露给了外网 HostC。

相当于在 HostA 上启动了 frpc,而再 HostC 上启动了 frps。

本地 socks5 代理

在 HostA 的本地 1080 端口启动一个 socks5 服务,通过本地 socks5 代理的数据会通过 ssh 链接先发送给 HostB,再从 HostB 转发送给远程主机:

HostA$ ssh -D localhost:1080  HostB

那么在 HostA 上面,浏览器配置 socks5 代理为127.0.0.1:1080, 看网页时就能把数据通过 HostB 代理出去,类似 ss/ssr 版本,只不过用 ssh 来实现。

使用优化

为了更好用一点,ssh 后面还可以加上:-CqTnN 参数,比如:

$ ssh -CqTnN -L 0.0.0.0:PortA:HostC:PortC  user@HostB

其中:

  • -C:为压缩数据,
  • -q:安静模式,
  • -T:禁止远程分配终端,
  • -n:关闭标准输入,
  • -N:不执行远程命令。
  • -f:参数,把 ssh 放到后台运行。

这些 ssh 代理没有短线重连功能,链接断了命令就退出了,所以需要些脚本监控重启, 或者使用 autossh 之类的工具保持链接。

功能对比

  • 正向代理(-L)的第一种用法可以用 iptable 的 port-forwarding 模拟, iptable 性能更好,但是需要 root 权限,ssh -L性能不好,但是正向代理花样更多些。
  • 反向代理(-R)一般就作为没有安装 frp/ngrok/shootback 时候的一种代替, 但是数据传输的性能和稳定性当然 frp 这些专用软件更好。
  • socks5 代理(-D)其实是可以代替 ss/ssr 的,区别和上面类似。所以要长久使用, 推荐安装对应软件,临时用一下 ssh 挺顺手。

补充下 iptable 的 port-forwarding 怎么设置,十分管用的功能,两个函数即可:


#! /bin/sh

# create forward rule by source interface
# http://serverfault.com/questions/532569/how-to-do-port-forwarding-redirecting-on-debian
PortForward1() {
    local IN_IF=$1
    local IN_PORT=$2
    local OUT_IP=$3
    local OUT_PORT=$4
    local IPTBL="/sbin/iptables"
    echo "1" > /proc/sys/net/ipv4/ip_forward
    $IPTBL -A PREROUTING -t nat -i $IN_IF -p tcp --dport $IN_PORT -j DNAT --to-destination ${OUT_IP}:${OUT_PORT}
    $IPTBL -A FORWARD -p tcp -d $OUT_IP --dport $OUT_PORT -j ACCEPT
    $IPTBL -A POSTROUTING -t nat -j MASQUERADE
}

# create forward rule by source ip
# http://blog.csdn.net/zzhongcy/article/details/42738285
ForwardPort2() {
    local IN_IP=$1
    local IN_PORT=$2
    local OUT_IP=$3
    local OUT_PORT=$4
    local IPTBL="/sbin/iptables"
    echo "1" > /proc/sys/net/ipv4/ip_forward
    $IPTBL -t nat -A PREROUTING --dst $IN_IP -p tcp --dport $IN_PORT -j DNAT --to-destination ${OUT_IP}:${OUT_PORT}
    $IPTBL -t nat -A POSTROUTING --dst $OUT_IP -p tcp --dport $OUT_PORT -j SNAT --to-source $IN_IP
}

第一个函数是按照网卡名称设置转发:

PortForward1 eth1 8765 202.115.8.2 8765

这时,本地 eth1 网卡的8765端口就会被转发给202.115.8.28765端口。

第二个函数是按照本机的 ip 地址,比如本机是192.168.1.2

PortForward2 192.168.1.2 8765 202.115.8.2 8765

那么任何访问本机192.168.1.2这个地址8765端口,都会被转发到202.115.8.2:8765

这个 iptable 的 port forwarding 是内核层运行的,性能极好, 只不过每次重启都需要重新设置下。

配置文件

基本语法

按服务器器保存配置在~/.ssh/config,方便以后连接:

Host Server1
    Hostname 172.16.0.1
    User zhangsan
    Port 22
    ServerAliveInterval 180
    IdentityFile ~/.ssh/secret_key.pem

每台服务器都可以定义一段配置:

  1. 起个名字Server1
  2. 它的 IP 是172.16.0.1(也可以填 Hostname)
  3. 用户名是zhangsan
  4. SSH 服务监听端口号为22(即默认值,也可以不写这一行)
  5. ServerAliveInterval 180表示在建立连接后, 每 180 秒客户端会向服务器发送一个心跳,避免用户长时间没操作连接中断
  6. 最后一行表示使用一个专用的密钥,如果没有专用的密钥则删除该行即可。

以后连接直接输入:

ssh Server1

复制文件的命令也简化很多:

scp /path/to/local/file Server1:/path/to/remote/

配置免密也相同,输入以下命令并输入密码:

ssh-copy-id Server1

通配符配置

如果有一批服务器都是相同的配置,更是可以用通配符统一处理:

Host Server*
    User zhangsan
    Port 22
    ServerAliveInterval 180

Host Server1
    Hostname 172.16.0.1

Host Server2
    Hostname 172.16.0.2

Host Server3
    Hostname 172.16.0.3

第一段表示所有名字为Server*开头的服务器, 然后下面列了 3 台服务器,我们只需要指定它们的 IP 地址。

多文件管理

如果需要管理非常多的服务器,全写到一个文件里会很乱很难维护。 ~/.ssh/config中支持引用其它文件。

新建一个这样的配置~/.ssh/config-cluster-shanghai, 然后在~/.ssh/config的开头加入如下一行即可:

Include config-cluster-shanghai

事实上这里也可以用通配符,比如:

Include config-*

这样~/.ssh/目录下的所有config-*开头的文件都会被引用到。

跳板

很多集群需要跳板机才可登录,我们需要先登录跳板机,再从跳板机登录内部机器。 这会引入两个麻烦,一是登录要两次, 如果配置 SSH config 还需要在跳板机也配置一份儿; 二是拷贝文件十分麻烦,要拷贝两次。

对此可以这样写配置:

Host Jumper
    Hostname 1.2.3.4
    User zhangsan

Host Server*
    User zhangsan
    ProxyJump Jumper
    ServerAliveInterval 180

Host Server1
    Hostname 172.16.0.1

Host Server2
    Hostname 172.16.0.2

第一段为跳板机的登录方式,第二段中新增了一个ProxyJump字段, 表示所有 Server 开头的服务器,在登录的时候都要从 Jumper 这个服务器跳转一下。 这时候我们想登录172.16.0.1,只需要直接输入:

ssh Server1
scp /path/to/local/file Server1:/path/to/remote/

注意一个细节是,这种配置下我们是直接从本地登录内部服务器,所以在配置免密时, 是需要把本地的公钥放到内部服务器的。

SCP 服务器间拷贝文件

scp 的基本用法相信大家都会,上文也多次提到。但如果想在两台服务器之间拷贝文件, 事实上是可以在本地执行 scp 的:

scp Server1:/path/to/file Server2:/path/to/file2

这个命令要求Server1可以直接访问Server2。如果不满足这个条件,可以用本机转发, 只需要增加一个参数-3表示用本地机器当转发机:

scp -3 Server1:/path/to/file Server2:/path/to/file2