陈日志 发布的文章

shadow文件的格式就不说了。就说说它的第二列——密码列。

通常,passwd直接为用户指定密码就ok了。但在某些情况下,要为待创建的用户事先指定密码,还要求是加密后的密码,例如kickstart文件中的rootpw指令,ansible创建用户时提前指定密码等,这时候不得不手动生成合理的密码。

先说说shadow文件中第二列的格式,它是加密后的密码,它有些玄机,不同的特殊字符表示特殊的意义:

  • ①.该列留空,即"::",表示该用户没有密码。
  • ②.该列为"!",即":!:",表示该用户被锁,被锁将无法登陆,但是可能其他的登录方式是不受限制的,如ssh公钥认证的方式,su的方式。
  • ③.该列为"",即"::",也表示该用户被锁,和"!"效果是一样的。
  • ④.该列以"!"或"!!"开头,则也表示该用户被锁。
  • ⑤.该列为"!!",即":!!:",表示该用户从来没设置过密码。
  • ⑥.如果格式为"$id$salt$hashed",则表示该用户密码正常。其中$id$的id表示密码的加密算法,$1$表示使用MD5算法,$2a$表示使用Blowfish算法,"$2y$"是另一算法长度的Blowfish,"$5$"表示SHA-256算法,而"$6$"表示SHA-512算法,

目前基本上都使用sha-512算法的,但无论是md5还是sha-256都仍然支持。$salt$是加密时使用的salt,hashed才是真正的密码部分。

下文都以生成明文"123456"对应的加密密码为例。

要生成md5算法的密码,使用openssl即可。

[root@server1 ~]# openssl passwd -1 '123456'
[root@server1 ~]# openssl passwd -1 -salt 'abcdefg' '123456'

生成密码后,直接将其拷贝或替换到shadow文件的第二列即可。例如:替换root用户的密码

shell> field=$(awk -F ':' '/^root/{print $2}' /etc/shadow)
shell> password=$(openssl passwd -1 123456)
shell> sed -i '/^root/s%'$field'%'$password'%' /etc/shadow

但openssl passwd不支持生成sha-256和sha-512算法的密码。在CentOS 6上,可以借助grub提供的密码生成工具grub-crypt生成。

[root@server1 ~]# grub-crypt -h
Usage: grub-crypt [OPTION]...
Encrypt a password.

  -h, --help              Print this message and exit
  -v, --version           Print the version information and exit
  --md5                   Use MD5 to encrypt the password
  --sha-256               Use SHA-256 to encrypt the password
  --sha-512               Use SHA-512 to encrypt the password (default)

Report bugs to <[email protected]>.
EOF
[root@server1 ~]# grub-crypt --sha-512
Password: 
Retype password: 
$6$nt4hMDAYqYjudvfo$AKIZ3Z0o6/6HV6GKXqq21VEmh.ADFAZUQw2mvbIlplKx7gu9MQiEWjdmHnF2YPnYzgce1cP/bzDguVnUkMg/N.

grub-crypt其实是一个python脚本,交互式生成密码。以下是grub-crypt文件的内容。

[root@server1 ~]# cat /sbin/grub-crypt
#! /usr/bin/python

'''Generate encrypted passwords for GRUB.'''

import crypt
import getopt
import getpass
import sys

def usage():
    '''Output usage message to stderr and exit.'''
    print >> sys.stderr, 'Usage: grub-crypt [OPTION]...'
    print >> sys.stderr, 'Try `$progname --help\' for more information.'
    sys.exit(1)

def gen_salt():                      # 生成随机的salt
    '''Generate a random salt.'''
    ret = ''
    with open('/dev/urandom', 'rb') as urandom:
        while True:
            byte = urandom.read(1)
            if byte in ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
                        './0123456789'):
                ret += byte
                if len(ret) == 16:
                    break
    return ret

def main():
    '''Top level.'''
    crypt_type = '$6$' # SHA-256
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hv',
                                   ('help', 'version', 'md5', 'sha-256',
                                    'sha-512'))
    except getopt.GetoptError, err:
        print >> sys.stderr, str(err)
        usage()
    if args:
        print >> sys.stderr, 'Unexpected argument `%s\'' % (args[0],)
        usage()
    for (opt, _) in opts:
        if opt in ('-h', '--help'):
            print (
'''Usage: grub-crypt [OPTION]...
Encrypt a password.

  -h, --help              Print this message and exit
  -v, --version           Print the version information and exit
  --md5                   Use MD5 to encrypt the password
  --sha-256               Use SHA-256 to encrypt the password
  --sha-512               Use SHA-512 to encrypt the password (default)

Report bugs to <[email protected]>.
EOF''')
            sys.exit(0)
        elif opt in ('-v', '--version'):
            print 'grub-crypt (GNU GRUB 0.97)'
            sys.exit(0)
        elif opt == '--md5':
            crypt_type = '$1$'
        elif opt == '--sha-256':
            crypt_type = '$5$'
        elif opt == '--sha-512':
            crypt_type = '$6$'
        else:
            assert False, 'Unhandled option'
    password = getpass.getpass('Password: ')
    password2 = getpass.getpass('Retype password: ')
    if not password:
        print >> sys.stderr, 'Empty password is not permitted.'
        sys.exit(1)
    if password != password2:
        print >> sys.stderr, 'Sorry, passwords do not match.'
        sys.exit(1)
    salt = crypt_type + gen_salt()
    print crypt.crypt(password, salt)      # 生成最终的加密密码

if __name__ == '__main__':
    main()

很不幸,CentOS 7上默认安装的是grub2,它不提供grub-crypt。因此参照grub-crypt内容,使用下面的python语句简单代替grub-crypt,这同样也是交互式的。

python -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'

如果不想交互式,再改成如下形式:

[root@server1 ~]# python -c 'import crypt,getpass;pw="123456";print(crypt.crypt(pw))'

现在就方便多了,直接将结果赋值给变量即可。

[root@server1 ~]# a=$(python -c 'import crypt,getpass;pw="123456";print(crypt.crypt(pw))')
[root@server1 ~]# echo $a
$6$uKhnBg5A4/jC8KaU$scXof3ZwtYWl/6ckD4GFOpsQa8eDu6RDbHdlFcRLd/2cDv5xYe8hzw5ekYCV5L2gLBBSfZ.Uc166nz6TLchlp.

例如,ansible创建用户并指定密码:

a=$(python -c 'import crypt,getpass;pw="123456";print(crypt.crypt(pw))')
ansible  192.168.100.55 -m user -a 'name=longshuai5 password="$a" update_password=always'

CDN 简介

什么是 CDN

为了解决互联网上越来越多内容的传输、存储、分发等问题,提供给终端用户更好的访问和使用体验,CDN 便是一个高性价比,操作便捷,快速实现的解决方案。CDN(Content Delivery Network),是在现有 Internet 中增加一层新的网络架构,由遍布全国的高性能加速 节点构成。这些高性能的服务节点都会按照一定的缓存策略存储您的业务内容,当您的用户 向您的某一业务内容发起请求时,请求会被调度至最接近用户的服务节点,直接由服务节点 直接快速响应,有效降低用户访问延迟,提升可用性。

CDN 的基本原理

假设您的业务源站域名为 www.test.com ,当域名接入 CDN 开始使用加速服务后,您
的用户发起 HTTP 请求,实际的处理流程如图所示:
图 1 CDN 基础流程示意图

- 阅读剩余部分 -

在平时管理Linux服务器中,可能会需要运行一些图形程序,那么我们在 Xshell 中能不能打开 GUI 程序呢?答案是可以的,使用 Xshell 和 Xmanager 就能非常简单的实现这个功能。

Linux 安装依赖包

yum install -y xorg-x11-xauth xorg-x11-utils xorg-x11-fonts-*

如果你要允许的GUI程序是中文界面的,则要安装中文字体或拷贝一个中文字体到/usr/share/fonts/下,否则的话会出现乱码。

Xshell 配置 X11 转发到 Xmanager

配置X11转发.png

* 注意:需要重新打开一个标签页才能生效

效果

​ 以 firewall-config GUI 程序为例

firewall-config示例.png

平时在对 Linux 服务器维护中,经常会有这样的情形:

远端服务器有多台机器,只有一台机器是映射外网端口的,我们没办法直接访问另外的服务器的服务。

local-remote-top.png

如图所示,服务器侧有A、B两台机器,只有 A 服务器开放了外网访问。客户端侧就没办法直接访问 B 服务器

客户端想要访问 B,常见的方法有:

  1. 在 A 上做防火墙规则做端口转发,如将 88 端口转发到 B 的 80 端口。

​ 但是这样有一个前提,开放了外网访问的服务器要有空闲的端口才行。

  1. 用 Xshell 的转移规则来实现

- 阅读剩余部分 -