苏苏的博客

简约至极

SSH

避免SSH自动断开连接

如果有一段时间在SSH连接上无数据传输,连接就会断开,以下设定可以解决这个问题

方案一:在客户端设置

sudo vim /etc/ssh/ssh_config

开启 ServerAliveInterval 60 开启 TCPKeepAlive yes

此后该系统里的用户连接SSH时,每60秒会发一个KeepAlive请求,避免被踢。

方案二:在服务器端设置

sudo vim /etc/ssh/sshd_config

开启ClientAliveInterval 60 开启 TCPKeepAlive yes

如果您只想让当前的 ssh 保持连接,可以使用以下的命令:

ssh -o ServerAliveInterval=60 user@sshserver

ssh 链接复用

Host *
ForwardAgent yes
ServerAliveInterval 30
ServerAliveCountMax 20
TCPKeepAlive no
ControlMaster auto
ControlPath ~/.ssh/connection-%r@%h:%p
ControlPersist 20m
Compression yes

http://einverne.github.io/post/2017/05/ssh-keep-alive.html

https://www.cyberciti.biz/faq/linux-unix-reuse-openssh-connection/

ssh隧道

CfNg参数

  • C表示压缩数据传输
  • f表示后台用户验证,这个选项很有用,没有shell的不可登陆账号也能使用.
  • N表示不执行脚本或命令
  • g表示允许远程主机连接转发端口,往往会没有效果,需要修改/etc/ssh/sshd_config添加gatewayports yes
  • T禁止分配伪终端,如果ssh使用此选项登录系统时,由于禁用,将无法获得终端;但仍能够获得shell,只不过看起来像在本地,也没有很多应有的环境变量,例如命令提示符,PS1等
  • n Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background

-L本地转发

-L [本地监听IP:]本地监听端口号:目标主机IP:目标端口号 (其中,“本地监听IP”可以省略,省略的话就认为是“0.0.0.0”,但为了安全性考虑,请务必使用“127.0.0.1”做为本地监听端口, 而不要使用默认的“0.0.0.0”。)

ssh -D 8080 user@host SSH会建立一个socket,去监听本地的8080端口。一旦有数据传向那个端口,就自动把它转移到SSH连接上面,发往远程主机。可以想象,如果8080端口原来是一个不加密端口,现在将变成一个加密端口。

ssh -L 2121:host2:21 host3 命令中的L参数一共接受三个值,分别是"本地端口:目标主机:目标主机端口”,它们之间用冒号分隔。这条命令的意思,就是指定SSH绑定本地端口2121,然后指定host3将所有的数据,转发到目标主机host2的21端口(假定host2运行FTP,默认端口为21)。 这样一来,我们只要连接host1的2121端口,就等于连上了host2的21端口。

ssh -CTfNg -L 6300:127.0.0.1:1521 oracle@172.16.1.164

本机的6300端口就是远程主机172.16.1.164的1521端口

socket 转发

OpenSSH 自 6.7 开始支持sock文件转发,将远程sock文件映射到本地.

例如将远程docker的socket映射到本地

ssh -CTfNng -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote

通过跳板机映射socket

ssh -CTfNng -L $(pwd)/docker.sock:/var/run/docker.sock -o "ProxyCommand ssh -q -W %h:%p -p 27897 user@gateway" -p 61177 user@someremote

export DOCKER_HOST=unix://$(pwd)/docker.sock 本机就可以连接docker了

ssh 跳板 (ssh over ssh)

ssh -o 'ProxyCommand ssh -q -W %h:%p root@transferip' root@targetip

ssh over socks5

ssh -o ProxyCommand='nc -x 192.0.2.0:1080 %h %p' user@targetip

测试发现苹果自带的nc 使用-x会有一些问题,总是还未连上时stdin就输入一些数据,导致链接不成功.

brew install nmap 安装Linux版本的nmap,安装后就会有ncat nmap nping ndiff等命令

ssh -o 'ProxyCommand ncat --proxy-type socks5 --proxy 172.168.1.3:2388 %h %p' -p port root@hostip

nc 的参数-x 指定了使用sock5代理

有了ssh over socks5, ssh over ssh 还可以以另一种方式实现

ssh -D 127.0.0.1:1080 user1@ssh-server1 先打通一个本地socks5,然后再使用ssh over socks5

注意 Linux 的 ncat 版本 使用代理的参数并非-x

nc --proxy 192.168.1.85:2388 --proxy-type socks5 targetip targetport

ssh over socks5 proxy + socket 映射

ssh -CTfNng -L /var/run/docker.sock:/var/run/docker.sock -o 'ProxyCommand ncat --proxy-type socks5 --proxy 172.168.1.3:2388 %h %p' -p 61177 root@targetip

https://github.com/ernw/static-toolbox/releases

参考 : https://www.robberphex.com/2015/09/426

-R远程转发

 ssh -CTfNg -R 1521:127.0.0.1:6300 oracle@172.16.1.164

在远程主机172.16.1.164上打开1521端口, 来映射本机的6300端口.

在树莓派上映射ssh到外网

ssh -CTfNg -R 2222:127.0.0.1:22 username@yourvps.com

这样就映射vps的2222端口到树莓派上了.但是这样映射的是服务器的127.0.0.1:2222,外网无法连接这个2222端口

如果你自己的服务器连接时需要端口可以在最后加上 -p port 指定ssh的端口

可以在服务器上执行netstat -anltp查看,这样要先登陆到自己的vps才能通过2222访问树莓派.

可以使用

ssh -CTfNg -R 0.0.0.0:2222:127.0.0.1:22 username@yourvps.com

再在服务器上配置/etc/ssh/sshd_config

#增加下面一句
GatewayPorts yes
#如果有
GatewayPorts no
#则改为
GatewayPorts yes
#然后重启ssh
#centos7: systemctl restart sshd
#centos6: service sshd restart
#ubuntu:   service ssh restart

使用netstat -anltp查看,监听的已经是0.0.0.0了,不过即使你指定-R参数127.0.0.1:2222,也不会监听127.0.0.1而始终是0.0.0.0

若没有netstat可考虑安装yum install lsof net-tools

使用下面的脚本可以保持断开自动重连,可以作为frp穿透的简单替代

需事先配置好ssh免密码登陆

先编写一个可执行脚本,例如 /home/osmc/.autossh

#!/bin/bash
while true; do ssh -CTNg -R 2222:127.0.0.1:2222 -p 23 username@yourvps.com; sleep 5;done;

赋予执行权限 chmod +x /home/osmc/.autossh

编写service文件 使用systemd开机启动

/etc/systemd/system/autossh.service

[Unit]
Description=autossh service
After=network.target network-online.target

[Service]
User=osmc
Restart=on-failure
TimeoutStartSec=0
ExecStart=/home/osmc/.autossh

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload sudo systemctl enable autossh sudo systemctl start autossh

sudo systemctl status autossh -l 查看状态 此方法存在缺陷,有时候断开无法连接上,最好还是使用frp

使用socks5代理

alias socksproxy="ssh -NT -f -C -D 0.0.0.0:1090  -p 1234 root@host";

-D 绑定地址 -N 不打开远程的shell -T 不分配tty -f 后台运行 -C 使用压缩

执行socksproxy后就建立了一条ssh socks5 proxy,本地使用127.0.0.1:1090就可以使用服务器中转流量.

ssh 服务

chkconfig --list可以查看所有服务是否开机启动等.

chkconfig --list sshd可以单独查看sshd服务的启动状态

/var/empty/sshd文件夹是sshd所必须的,不能被删除否则ssh服务将无法启动

chkconfig sshd on将其设置为开机启动

CentOS7 用systemctl取代了service 旧版本的 chkconfig docker on 改为 systemctl enable docker

https://www.ssh.com/ssh/copy-id

ssh 使用了ssh-copy-id 任然不能免密码登录问题

  1. 检查权限问题
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

## 如果上面还不行,使用这个
chmod 700 ~/.ssh ; chmod 600 ~/.ssh/authorized_keys ; chmod g-w,o-w ~  ## chmod go-w ~

## 验证文件夹所属权
chown -R root ~
chgrp -R root ~/.ssh/
  1. 确保sshd配置文件没有禁用密匙验证
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile  %h/.ssh/authorized_keys

sshd 配置文件

grep -Ev '''^(#|$)''' sshd_config 可查看有效的配置(排除注释)

/etc/ssh/sshd_config

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
AuthorizedKeysFile	.ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding no
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem	sftp	/usr/libexec/openssh/sftp-server

编译openssh

http://www.openssh.com/ftp.html

在alpine中编译openssh,镜像地址 http://ftp.jaist.ac.jp/pub/OpenBSD/OpenSSH/portable/

编译完成后得到一些工具,如scp,sftp-server,ssh,sshd等等

apk update && apk upgrade
apk --update add make curl gcc g++ zlib-dev openssl-dev
cd /tmp
OPENSSH_VERSION=openssh-7.6p1
CPU_NUM=`cat /proc/cpuinfo | grep processor | wc -l`
curl http://ftp.jaist.ac.jp/pub/OpenBSD/OpenSSH/portable/${OPENSSH_VERSION}.tar.gz | tar xz
cd ${OPENSSH_VERSION}
./configure
make -j$CPU_NUM CFLAGS="-Os" LDFLAGS="-static -L./ -L./openbsd-compat/"  && make install

即可静态编译.

我编译好的二进制文件,能直接用于alpine系统

配合Linuxadduser,可以ssh到docker中

curl -o /usr/local/bin/sshd.xz http://share.suconghou.cn/files/bin/sshd.xz

sshd运行不能直接执行sshd,需要执行/usr/local/bin/sshd

配置文件为/usr/local/etc/sshd_config,同时还需要几个密匙文件.

curl -o /usr/local/bin/sshd.xz http://share.suconghou.cn/files/bin/sshd.xz
xz -d /usr/local/bin/sshd.xz
chmod +x /usr/local/bin/sshd
mkdir -p /usr/local/etc/
touch /usr/local/etc/sshd_config
ssh-keygen -t dsa -f /usr/local/etc/ssh_host_dsa_key -N ''
ssh-keygen -t rsa -f /usr/local/etc/ssh_host_rsa_key -N ''
ssh-keygen -t ecdsa -f /usr/local/etc/ssh_host_ecdsa_key -N ''
ssh-keygen -t ed25519 -f /usr/local/etc/ssh_host_ed25519_key -N ''

添加一个用户:adduser work ,Alpine里是adduser,Linux发行版里是useradd

adduser work -M -N

cat /etc/passwd 可以查看所有用户的列表,只输出用户名可以cat /etc/passwd |cut -f 1 -d :

看第三个参数:500以上的,就是后面建的用户了.其它则为系统的用户.

cat /etc/group 查看用户组

非交互式修改密码

在 Linux 中 passwd echo "1234" | passwd --stdin work

在alpine/buxybox 中 chpasswd echo "1234" | chpasswd (默认修改当前用户的密码)

w 可以查看当前活跃的用户列表

删除用户userdel , 用户userdel -r 用户名,删除用户账户及用户主目录文件

没有外网IP还可以使用ssh建立一个隧道

ssh -CfNg -R 0.0.0.0:2233:127.0.0.1:22 root@yourvps.com -p 27558

编译dropbear

dropbear 是一个更加小巧的sshd

https://matt.ucc.asn.au/dropbear/dropbear.html

cd /tmp
apk update && apk upgrade && apk add wget make gcc g++ linux-headers
wget --no-check-certificate  https://matt.ucc.asn.au/dropbear/releases/dropbear-2017.75.tar.bz2
tar jxvf dropbear-2017.75.tar.bz2 && cd dropbear-2017.75
CFLAGS="-Os -ffunction-sections -fdata-sections" LDFLAGS="-static -Wl,--gc-sections" ./configure --disable-zlib
make -j2

不到一分钟即可编译完成

mkdir /etc/dropbear

后台运行 ./dropbear -E -R -m 不进入后台 ./dropbear -F -E -R -m

-m 意味着用户登陆成功后不显示/etc/motd文件内的提示.

dbclient 是一个和ssh类似的客户端

然后linux系统的用户即可通过22端口登陆

CentOS7修改ssh端口

注意:修改ssh端口后,可能还是不能使用,主要原因可能是semanage

使用以下命令查看当前SElinux 允许的ssh端口: semanage port -l | grep ssh

添加xxxx端口到 SELinux semanage port -a -t ssh_port_t -p tcp xxxx 然后确认一下是否添加进去 semanage port -l | grep ssh 如果成功会输出 ssh_port_t tcp xxxx, 22

autossh

sudo yum install gcc make

wget http://www.harding.motd.ca/autossh/autossh-1.4e.tgz
tar zxf autossh-1.4e.tgz
cd autossh-1.4e
./configure && make

zsh

Ctrl + a :移到命令行首 Ctrl + e :移到命令行尾 Ctrl + r:逆向搜索命令历史 Ctrl + g:从历史搜索模式退出 Ctrl + p:历史中的上一条命令 Ctrl + n:历史中的下一条命令

http://jaywcjlove.github.io/handbook/html/Vim%E7%90%86%E8%A7%A3.html

sudo 记住密码时间

mac 系统 在第一次执行sudo命令后,默认情况下密码将持续15分钟,因此您不需要为每个sudo命令键入密码

可以修改 /etc/sudoers 文件配置该时间 使用 sudo visudo 修改此文件

Defaults        env_reset,timestamp_timeout=60

这里设置为1小时

如果要为每个执行的sudo命令输入密码提示,也可以将时间设置为0

ssh 远程执行后台命令

&>/dev/null >/dev/null 2>/dev/null >/dev/null 2>&1 三者是等价的。

https://www.gnu.org/software/bash/manual/bash.html#Redirecting-Standard-Output-and-Standard-Error

1.sh 是一个耗时操作

ping -c 10 8.8.8.8
ssh user@host "/1.sh"

客户端会执行等待执行完后退出,客户端显示脚本的输出,中途客户端终止,脚本立即终止执行

ssh user@host "nohup /1.sh"

ssh user@host "nohup /1.sh &"

这两种与第一种结果一样.

如果想要后台运行,需要

ssh user@host "nohup /tmp/1.sh >/dev/null &"

至少需要把标准输出重定向到一个文件才行。

这样做 更保险

ssh user@host "nohup myprogram > foo.out 2> foo.err < /dev/null &"

要做到显示一部分数据,然后后台呢?

修改我们要执行的脚本 1.sh

echo "go to background"

nohup ping -c 20 t.cn &>/dev/null &

echo "ping is in background "

ps aux | grep ping

客户端执行 ssh user@host "/1.sh"

需要注意的是,这里 nohup 加不加都可以,但是最后的&符号必须,否则会造成客户端等待。

即使使用 nohup&, 重定向标准输出始终是必须的,否则造成客户端等待,并打印这些输出,至少需重定向标准输出。

nohup ping -c 20 t.cn &>/dev/null </dev/null &

ssh直接开启后台任务:

ssh user@host "nohup ping -c 10 t.cn &>/dev/null </dev/null &"

>/dev/null 2>&1 注意 2>&1 必须放在后面

linx rsync

server

rsync --daemon --port 15577

client