SSH Google Authenticator

Docker构建SSH服务镜像

基于alpine构建,拉取alpine镜像

1
2
3
4
5
6
7
> docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
59bf1c3509f3: Already exists
Digest: sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest

编写Dockerfile文件

安装 Google Authenticator

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# sshd
#
# VERSION               0.0.1

FROM     alpine:latest
MAINTAINER ph "xx@gmail.com"

# make sure the package repository is up to date
# make sure the package repository is up to date
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
    && apk update \
    && apk add --no-cache openssh tzdata \
    && apk add openssh openssh-server-pam google-authenticator openssh-doc google-authenticator-doc \
    && touch /etc/pam.d/sshd \
    && ln /etc/pam.d/sshd /etc/pam.d/sshd.pam \
    && echo "auth required pam_google_authenticator.so no_increment_hotp noskewadj" >> /etc/pam.d/sshd \
    && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && sed -i "s/#PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config \
    && sed -i "s/#PasswordAuthentication yes/PasswordAuthentication yes/g" /etc/ssh/sshd_config \
    && sed -i "/#UsePAM no/i\ChallengeResponseAuthentication yes" /etc/ssh/sshd_config \
    && sed -i "s/#UsePAM no/UsePAM yes/g" /etc/ssh/sshd_config \
    && ssh-keygen -t dsa -P "" -f /etc/ssh/ssh_host_dsa_key \
    && ssh-keygen -t rsa -P "" -f /etc/ssh/ssh_host_rsa_key \ 
    && ssh-keygen -t ecdsa -P "" -f /etc/ssh/ssh_host_ecdsa_key \
    && ssh-keygen -t ed25519 -P "" -f /etc/ssh/ssh_host_ed25519_key \
    && echo "root:abc123456" | chpasswd

EXPOSE 22

CMD    ["/usr/sbin/sshd", "-D"]

sshd服务默认安装在/usr/sbin目录下,使用-D参数sshd服务在前台启动,从而让容器直接运行在sshd服务上。

执行build构建镜像

1
2
3
4
5
6
7
> docker build -t mysshd:alpine -f Dockerfile .
Step 5/5 : CMD    ["/usr/sbin/sshd", "-D"]
 ---> Running in f0931ddbdde5
Removing intermediate container f0931ddbdde5
 ---> bc74fe1ef269
Successfully built bc74fe1ef269
Successfully tagged mysshd:alpine

启动sshd容器服务

1
2
3
4
5
> docker run -d --name sshdocker -P mysshd:alpine
6153e6d0f9bb0cdcaf5612131d5649897eedb6d3b7e416a580a1637226090979
> docker ps
CONTAINER ID   IMAGE           COMMAND               CREATED         STATUS         PORTS                   NAMES
6153e6d0f9bb   mysshd:alpine   "/usr/sbin/sshd -D"   5 seconds ago   Up 4 seconds   0.0.0.0:55000->22/tcp   sshdocker

通过ssh客户端连接ssh服务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
> ssh -p 55000 root@127.0.0.1
The authenticity of host '[127.0.0.1]:55000 ([127.0.0.1]:55000)' can't be established.
ECDSA key fingerprint is SHA256:h8VR9hV6yP2WW38Bep3dPITVgr83JQ7JPCDpN3sbcjA.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[127.0.0.1]:55000' (ECDSA) to the list of known hosts.
root@127.0.0.1's password:
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org/>.

You can setup the system with the command: setup-alpine

You may change this message by editing /etc/motd.

6153e6d0f9bb:~# pwd
/root

生成密钥文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ google-authenticator
   Do you want authentication tokens to be time-based (y/n) y
   <这里是自动生成的二维码>
   Your new secret key is: ZVZG5UZU4D7MY4DH          (验证器配置密钥)
   Your verification code is 269371                  (输入验证器生成的验证码)
   Your emergency scratch codes are:                 (备用令牌码)
     70058954
     97277505
     99684896
     56514332
     82717798
   
   Do you want me to update your "/home/username/.google_authenticator" file (y/n) y
   (是否重新生成登录配置文件?)
   
   Do you want to disallow multiple uses of the same authentication
   token? This restricts you to one login about every 30s, but it increases
   your chances to notice or even prevent man-in-the-middle attacks (y/n) y
   (是否拒绝多次重复使用相同的令牌?这将限制你每30s仅能登录一次,但会提醒/阻止中间人攻击。)
   
   By default, tokens are good for 30 seconds and in order to compensate for
   possible time-skew between the client and the server, we allow an extra
   token before and after the current time. If you experience problems with poor
   time synchronization, you can increase the window from its default
   size of 1:30min to about 4min. Do you want to do so (y/n) n
   (是否将窗口时间由1分30秒增加到约4分钟?这将缓解时间同步问题。)
   
   If the computer that you are logging into is not hardened against brute-force
   login attempts, you can enable rate-limiting for the authentication module.
   By default, this limits attackers to no more than 3 login attempts every 30s.
   Do you want to enable rate-limiting (y/n) y
   (是否启用此模块的登录频率限制,登录者将会被限制为最多在30秒内登录3次。)

修改配置设置两步验证

编辑 /etc/pam.d/sshd 文件

1
2
3
4
5
6
account         include                         base-account

auth            required                        pam_env.so
auth            required                        pam_nologin.so  successok
auth            required                        /lib/security/pam_google_authenticator.so       echo_verification_code grace_period=57600 nullok
auth            required                        pam_unix.so      md5 sha512

重启sshd服务

参考