LXC 容器集chroot使用说明

1.1 LXC是什么?

1.1.1 关于LXC

LXC,其名称来自Linux软件容器(Linux Containers)的缩写,一种操作系统层虚拟化(Operating systemlevel virtualization)技术,为Linux内核容器功能的一个用户空间接口。它将应用软件系统打包成一个软件容器(Container,内含应用软件本身的代码,以及所需要的操作系统核心和库。通过统一的名字空间和共用API来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得Linux用户可以容易的创建和管理系统或应用容器。

LXC 容器集chroot使用说明

- lxc官方logo

Linux内核中,提供了cgroups功能,来达成资源的区隔化。它同时也提供了名称空间区隔化的功能,使应用程序看到的操作系统环境被区隔成独立区间,包括进程树,网络,用户id,以及挂载的文件系统。但是cgroups并不一定需要引导任何虚拟机。

LXC利用cgroups与名称空间的功能,提供应用软件一个独立的操作系统环境。LXC不需要Hypervisor这个软件层,软件容器(Container)本身极为轻量化,提升了创建虚拟机的速度。软件Docker被用来管理LXC的环境。

1.1.2 关于操作系统层虚拟化

操作系统层虚拟化(英语:Operating systemlevel virtualization),一种虚拟化技术,这种技术将操作系统内核虚拟化,可以允许使用者空间软件物件(instances)被分割成几个独立的单元,在内核中运行,而不是只有一个单一物件运行。这个软件物件,也被称为是一个容器(containers),虚拟引擎(Virtualization engine),虚拟专用服务器(virtual private servers)或是 jails。对每个行程的拥有者与使用者来说,他们使用的服务器程式,看起来就像是自己专用的。

操作系统层虚拟化之后,可以实现软件的即时迁移(Live migration,使一个软件容器中的物件,即时移动到另一个操作系统下,再重新执行起来。但是在这种技术下,软件即时迁移,只能在同样的操作系统下进行。

在类Unix操作系统中,这个技术最早起源于标准的chroot机制,再进一步演化而成。除了将软件独立化的机制之外,内核通常也提供资源管理功能,使得单一软件容器在运作时,对于其他软件容器的造成的交互影响最小化。

1.1.3 LXC的特点

目前的LXC使用下列内核功能来控制进程:

内核命名空间(进程间通信、utsmountpidnetworkuser

️ AppArmorSELinux配置

️ Seccomp策略

️ chroot(使用pivot_root

️ Kernel Capibilities

控制组(cgroups

因此,LXC通常被认为介于“加强版”的chroot和完全成熟的虚拟机之间的技术LXC的目标是创建一个尽可能与标准安装的Linux相同但又不需要分离内核的环境。

关于chroot可以参考:https://www.ibm.com/developerworks/cn/linux/l-cn-chroot/

1.1.4 LXC的应用

Docker

它在0.9版之前都是使用LXC技术,但在0.9版之后,已不再是唯一且默认的运行环境。

Proxmox VE

Proxmox VE是一个开源的服务器虚拟化环境Linux发行版。基于Debian,使用基于Ubuntu的定制内核。

它直到4.0版才使用LXC技术,在此之前的版本都是使用OpenVZ技术。

1.2 安装LXC

1.2.1 环境说明

官方文档:https://linuxcontainers.org/lxc/getting-started/

   安装LXC内核版本不能低于2.6.32,对lxc至此最佳的为Ubuntu系统。

宿主机环境说明:

[root@lxc ~]# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core) 
[root@lxc ~]# uname -r 
3.10.0-327.el7.x86_64
[root@lxc ~]# sestatus 
SELinux status:                 disabled
[root@lxc ~]# hostname -I
172.16.1.100 10.0.0.100

安装lxc需要使用到epel源,这里使用的是aliyun源站

[root@lxc ~]# yum install epel-release -y    
[root@lxc ~]# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

1.2.2 安装LXC

[root@lxc ~]# yum install lxc-* libcgroup* bridge-utils.x86_64 -y

包组说明

 lxc          lxc相关软件

 libcgroup    资源管理,限制

 bridge-utils 管理桥接网卡

1.2.3 修改网卡配置

创建桥接网卡

[root@lxc ~]#  cat /etc/sysconfig/network-scripts/ifcfg-eth0 
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
BRIDGE=br0
[root@lxc ~]#  cat /etc/sysconfig/network-scripts/ifcfg-br0 
TYPE=Bridge
BOOTPROTO=static
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=10.0.0.100
NETMASK=255.255.255.0
GATEWAY=10.0.0.254
DNS1=223.5.5.5

   修改lxc配置使用桥接网卡

[root@lxc ~]# vi /etc/lxc/default.conf 
lxc.network.type = veth
lxc.network.link = br0
lxc.network.flags = up

重启网卡

[root@lxc ~]# /etc/init.d/network restart 
Restarting network (via systemctl):                        [  确定  ]

查看桥接信息

[root@lxc ~]# brctl show
bridge name    bridge id        STP enabled    interfaces
br0        8000.000c29c008a6    no        eth0

1.2.4 启动服务

[root@lxc ~]# systemctl restart cgconfig.service 
[root@lxc ~]# systemctl enable cgconfig.service 
[root@lxc ~]# ystemctl restart lxc.service

1.3 启动第一个LXC容器

参考方法: https://mirrors.tuna.tsinghua.edu.cn/help/lxc-images/

lxc启动容器时,推荐使用ubuntu/centos6系统,centos7系统使用会有问题。

[root@docker01 ~]# lxc-create -t download -n centos7 -- --server mirrors.tuna.tsinghua.edu.cn/lxc-images -d centos -r 7 -a amd64

参数说明:

参数

说明

-t, --template=t

设置容器的模板.LXC 1.0 以上版本增加了 download 模版,支持下载定义好的系统镜像。

-n, --name=NAME

为容器设置名称

--server

指定服务器地址

-d DIST

发行版本

-r RELEASE

系统版本

-a ARCH

架构

查看你lxc的缓存文件位置

[root@lxc lxc]# cd /var/cache/lxc
[root@lxc lxc]# tree
.
└── download
    └── centos
        ├── 6
        │   └── amd64
        │       └── default
        │           ├── build_id
        │           ├── config
        │           ├── config-user
        │           ├── create-message
        │           ├── excludes-user
        │           ├── expiry
        │           ├── rootfs.tar.xz
        │           └── templates
        └── 7
            └── amd64
                └── default
                    ├── build_id
                    ├── config
                    ├── config-user
                    ├── create-message
                    ├── excludes-user
                    ├── expiry
                    ├── rootfs.tar.xz
                    └── templates

1.3.1 查看你当前容器列表

[root@lxc ~]# lxc-ls 
centos6  centos7  

1.3.2 修改容器的密码

修改密码使用chroot的方式进行修改

[root@lxc ~]# chroot /var/lib/lxc/centos7/rootfs/ passwd
Changing password for user root.
New password: 123456
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 123456
passwd: all authentication tokens updated successfully.

1.3.3 启动容器

在启动容器之前,先修改容器配置文件,添加ip地址信息

[root@lxc ~]# vim /var/lib/lxc/centos7/config
lxc.network.name = eth0
lxc.network.ipv4 = 10.0.0.111/24
lxc.network.ipv4.gateway = 10.0.0.254

   ip设置好后可以启动容器

[root@lxc ~]# lxc-start -n centos7 

centos7 login: root
Password: 
Last failed login: Wed Jan 31 10:12:22 UTC 2018 on lxc/console
There was 1 failed login attempt since the last successful login.
[root@centos7 ~]# yum install openssh-server -y 
[root@centos7 ~]# systemctl start sshd

1.3.4 启动容器的其他方法

lxc-create -t centos -n test

这种方法启动的容器会生成默认的密码

默认密码位置;

cat /var/lib/lxc/test/tmp_root_pass

1.4 LXC管理操作

LXC官方手册:http://lxc.sourceforge.net/man/

克隆一个容器

[root@docker01 ~]# lxc-clone  test  clsn-image
Created container clsn-image as copy of test

检查lxc配置

[root@docker01 ~]# lxc-checkconfig 
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled
···

持续观察容器的状态和优先级变化:

lxc-monitor -n name

 LXC 使用 cgroup 文件系统管理容器。

可以通过 LXC 读和操纵 cgroup 文件系统的一些部分。要管理每个容器对 cpu 的使用,则可以通过读取和调整容器的 cpu.shares 来进行:

lxc-cgroup -n name cpu.shares
lxc-cgroup -n name cpu.shares howmany

暂停和恢复

lxc-freeze -n name
lxc-unfreeze -n name

停止,停止一个容器将导致该容器中启动的所有进程全体死亡,并且清理容器:

lxc-stop -n name

销毁,销毁容器是指删除通过 lxc-create 步骤与名称关联的配置文件和元数据:

lxc-destroy -n name

查看容器当前状态

[root@lxc ~]# lxc-info --name centos6
Name:           centos6
State:          STOPPED

查看lxc使用进程情况

lxc-top

1.5 使用 chroot *限制 SSH 用户访问指定目录

1.5.1 当前网络威胁

暴露在互联网上的系统要将坏人隔离在外是一个很大的挑战,而且一直更新最新的安全补丁也不太容易。因此,一些聪明的管理员们尝试采用系统的方法来限制可能发生的入侵,这其中一个绝佳的方法就是使用chroot*(jail)。

chroot*极大地限制了应用程序可查看的文件系统范围,拥有更少的系统权限,这些都是为了限制应用程序误操作或者被坏人利用从而对系统造成损害。

本文简述一下chroot是如何工作的,并着重讨论一下开发者和管理员能够用到的一些最佳实践来让系统更加安全。

1.5.2 chroot做什么

SSH 用户会话限制访问到特定的目录内,特别是在 web 服务器上,这样做有多个原因,但最显而易见的是为了系统安全。为了锁定 SSH 用户在某个目录,我们可以使用 chroot 机制。

在诸如 Linux 之类的类 Unix 系统中更改 rootchroot)是将特定用户操作与其他 Linux 系统分离的一种手段;使用称为 chrooted * 的新根目录更改当前运行的用户进程及其子进程的明显根目录。

chroot系统调用将当前进程及其子进程的root目录修改到一个特定的路径,通常是在文件系统真正的root目录下的一些受限的子目录中。进程认为新的路径就是系统的“/”,因此我们将这个受限制的环境称为“*”。除非一些特殊手段,要从*里面逃出来是根本不可能的。

chroot系统调用存在于所有已知的UNIX版本中,它能够为运行的进程创建一个临时根目录,这种方法将一个受限制的文件系统(比如,/chroot/named)作为进程可见的最上层目录。

1.5.3 创建 SSH chroot *

1、使用 mkdir 命令开始创建 chroot *

[root@clsn ~]# mkdir -p /opt/clsn

2、根据 sshd_config 手册找到所需的文件,ChrootDirectory 选项指定在身份验证后要 chroot 到的目录的路径名。该目录必须包含支持用户会话所必需的文件和目录。

对于交互式会话,这需要至少一个 shell,通常为 sh 和基本的 /dev 节点,例如 nullzerostdinstdoutstderr tty 设备

[root@clsn ~]# ls -l /dev/{null,zero,stdin,stdout,stderr,random,tty}
crw-rw-rw- 1 root root 1, 3 Jan 31 13:24 /dev/null
crw-rw-rw- 1 root root 1, 8 Jan 31 13:24 /dev/random
lrwxrwxrwx 1 root root   15 Jan 31  2018 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root   15 Jan 31  2018 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root   15 Jan 31  2018 /dev/stdout -> /proc/self/fd/1
crw-rw-rw- 1 root tty  5, 0 Jan 31 13:24 /dev/tty
crw-rw-rw- 1 root root 1, 5 Jan 31 13:24 /dev/zero

3、使用 mknod 命令创建 /dev 下的文件。在下面的命令中,-m 标志用来指定文件权限位,c 意思是字符文件,两个数字分别是文件指向的主要号和次要号。

[root@clsn ~]# mkdir -p /opt/clsn/dev
[root@clsn ~]# cd /opt/clsn/dev
[root@clsn dev]# mknod -m 666 null c 1 3
[root@clsn dev]# mknod -m 666 tty c 5 0
[root@clsn dev]# mknod -m 666 zero c 1 5
[root@clsn dev]# mknod -m 666 random c 1 8

4、在 chroot *中设置合适的权限。注意 chroot *和它的子目录以及子文件必须被 root 用户所有,并且对普通用户或用户组不可写

[root@clsn dev]# chown root.root /opt/clsn
[root@clsn dev]# chmod 0755 /opt/clsn
[root@clsn dev]# ls -ld /opt/clsn
drwxr-xr-x 3 root root 4096 Jan 31 13:36 /opt/clsn

1.5.4 SSH chroot *设置交互式 shell

1、创建 bin 目录并复制 /bin/bash bin

[root@clsn dev]# mkdir -p /opt/clsn/bin
[root@clsn dev]# cp -v /bin/bash  /opt/clsn/bin/
`/bin/bash' -> `/opt/clsn/bin/bash'

2、识别 bash 所需的共享库,如下所示复制它们到 lib64

[root@clsn dev]# ldd /bin/bash 
    linux-vdso.so.1 =>  (0x00007fffb68fb000)
    libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003600a00000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00000035fee00000)
    libc.so.6 => /lib64/libc.so.6 (0x00000035ff200000)
    /lib64/ld-linux-x86-64.so.2 (0x00000035fea00000)
[root@clsn dev]# mkdir -p /opt/clsn/lib64
[root@clsn dev]# cp -v /lib64/{libtinfo.so.5,libdl.so.2,libc.so.6,ld-linux-x86-64.so.2} /opt/clsn/lib64/
`/lib64/libtinfo.so.5' -> `/opt/clsn/lib64/libtinfo.so.5'
`/lib64/libdl.so.2' -> `/opt/clsn/lib64/libdl.so.2'
`/lib64/libc.so.6' -> `/opt/clsn/lib64/libc.so.6'
`/lib64/ld-linux-x86-64.so.2' -> `/opt/clsn/lib64/ld-linux-x86-64.so.2'

1.5.5 创建并配置 SSH 用户

1、使用 useradd 命令创建 SSH 用户,并设置安全密码

[root@clsn dev]# useradd  clsn
[root@clsn dev]# echo 123456|passwd --stdin clsn 
Changing password for user clsn.
passwd: all authentication tokens updated successfully.

2、创建 chroot *通用配置目录 /opt/etc 并复制已更新的账号文件(/etc/passwd /etc/group)到这个目录中

[root@clsn dev]# mkdir -p /opt/clsn/etc
[root@clsn dev]# cp -vf /etc/{passwd,group} /opt/clsn/etc/
`/etc/passwd' -> `/opt/clsn/etc/passwd'
`/etc/group' -> `/opt/clsn/etc/group'

注意:每次向系统添加更多 SSH 用户时,都需要将更新的帐户文件复制到 /opt/clsn/etc/ 目录中。

1.5.6 配置 SSH 来使用 chroot *

1、配置sshd配置文件,/etc/ssh/sshd_config

cat >>/etc/ssh/sshd_config <<'EOF'
Match User clsn
ChrootDirectory /opt/clsn
EOF

配置参数说明

# 定义要使用 chroot *的用户
Match User clsn
# 指定 chroot *
ChrootDirectory /opt/clsn

2、重新启动sshd服务

[root@clsn dev]# /etc/init.d/sshd restart 
Stopping sshd:                                             [  OK  ]
Starting sshd:                                             [  OK  ]

1.5.7 测试 SSH chroot *

[C:\]$ ssh clsn@10.0.0.188
Connecting to 10.0.0.188:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
Last login: Wed Jan 31 13:49:31 2018 from mirrors.aliyuncs.com
-bash-4.1$
-bash-4.1$ ls
-bash: ls: command not found
-bash-4.1$ date
-bash: date: command not found

从上面可以看出 SSH 用户被锁定在了 chroot *中,并且不能使用任何外部命令如(lsdate等等)。

   用户只可以执行 bash 以及它内置的命令(比如:pwdhistoryecho 等等):

[C:\]$ ssh clsn@10.0.0.188
Connecting to 10.0.0.188:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
Last login: Wed Jan 31 13:49:31 2018 from mirrors.aliyuncs.com
-bash-4.1$
-bash-4.1$ ls
-bash: ls: command not found
-bash-4.1$ date
-bash: date: command not found

1.5.8 创建用户的主目录并添加 Linux 命令

1、从前面的测试中,我们可以看到用户被锁定在了根目录,我们可以为 SSH 用户创建一个主目录(为所有将来的用户可以这么做)

[root@clsn dev]# mkdir -p /opt/clsn/home/clsn
[root@clsn dev]# chown -R clsn.clsn /opt/clsn/home/clsn
[root@clsn dev]# chmod -R 0700 /opt/clsn/home/clsn

2、将在 bin 目录中复制进几个用户命令,如 lsdatemkdir

[root@clsn dev]# cp -v /bin/ls /opt/clsn/bin/
`/bin/ls' -> `/opt/clsn/bin/ls'
[root@clsn dev]# cp -v /bin/date /opt/clsn/bin/
`/bin/date' -> `/opt/clsn/bin/date'
[root@clsn dev]# cp -v /bin/mkdir /opt/clsn/bin/
`/bin/mkdir' -> `/opt/clsn/bin/mkdir'

3、接下来,检查上面命令的共享库并将它们移到 chroot *的库目录中

   查看ls命令共享库

[root@clsn dev]# ldd /bin/ls
    linux-vdso.so.1 =>  (0x00007ffe47abf000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003600600000)
    librt.so.1 => /lib64/librt.so.1 (0x00000035ffa00000)
    libcap.so.2 => /lib64/libcap.so.2 (0x0000003605200000)
    libacl.so.1 => /lib64/libacl.so.1 (0x0000003604600000)
    libc.so.6 => /lib64/libc.so.6 (0x00000035ff200000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00000035fee00000)
    /lib64/ld-linux-x86-64.so.2 (0x00000035fea00000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00000035ff600000)
    libattr.so.1 => /lib64/libattr.so.1 (0x0000003602e00000)

   复制共享库文件

[root@clsn dev]# \cp -v /lib64/{libselinux.so.1,libcap.so.2,libacl.so.1,libc.so.6,libdl.so.2,ld-linux-x86-64.so.2,libattr.so.1,libpthread.so.0,librt.so.1} /opt/clsn/lib64/ 
`/lib64/libselinux.so.1' -> `/opt/clsn/lib64/libselinux.so.1'
`/lib64/libcap.so.2' -> `/opt/clsn/lib64/libcap.so.2'
`/lib64/libacl.so.1' -> `/opt/clsn/lib64/libacl.so.1'
`/lib64/libc.so.6' -> `/opt/clsn/lib64/libc.so.6'
`/lib64/libdl.so.2' -> `/opt/clsn/lib64/libdl.so.2'
`/lib64/ld-linux-x86-64.so.2' -> `/opt/clsn/lib64/ld-linux-x86-64.so.2'
cp: cannot create regular file `/opt/clsn/lib64/ld-linux-x86-64.so.2': Text file busy
`/lib64/libattr.so.1' -> `/opt/clsn/lib64/libattr.so.1'
`/lib64/libpthread.so.0' -> `/opt/clsn/lib64/libpthread.so.0'

1.5.9 测试 sftp chroot *

1、用 sftp 做一个测试;测试你先前安装的命令是否可用。

   /etc/ssh/sshd_config 中添加下面的行

echo 'ForceCommand internal-sftp'  >> /etc/ssh/sshd_config

重启 sshd 服务

[root@clsn dev]# /etc/init.d/sshd restart 
Stopping sshd:                                             [  OK  ]
Starting sshd:                                             [  OK  ]

2、现在使用 ssh 测试,你会得到下面的错误:

[root@lx ~]# ssh clsn@10.0.0.188
clsn@10.0.0.188's password: 
This service allows sftp connections only.
Connection to 10.0.0.188 closed.

3、试下使用 sftp

   复制sftp程序

[root@clsn ~]# cp -v  /usr/libexec/openssh/sftp-server /opt/clsn/usr/libexec/openssh/ 
`/usr/libexec/openssh/sftp-server' -> `/opt/clsn/usr/libexec/openssh/sftp-server'

   sftp传输文件测试

[root@lx ~]# sftp clsn@10.0.0.188
clsn@10.0.0.188's password: 
Connected to 10.0.0.188.
sftp> pwd
Remote working directory: /home/clsn
sftp> mkdir -p nmtui
sftp> cd nmtui/
sftp> put  anaconda-ks.cfg  
Uploading anaconda-ks.cfg to /home/clsn/nmtui/anaconda-ks.cfg
anaconda-ks.cfg                                   100% 1207     1.2KB/s   00:00

   到远端进行查看

[root@clsn ~]# ll /opt/clsn/home/clsn/nmtui/
total 4
-rw------- 1 clsn clsn 1207 Jan 31 14:21 anaconda-ks.cfg

   至此chroot *就配置完成

1.6 参考文献

 [1] https://linuxcontainers.org

[2] https://zh.wikipedia.org/wiki/LXC

[3] https://www.ibm.com/developerworks/cn/linux/l-lxc-containers/

[4] https://www.tecmint.com/restrict-ssh-user-to-directory-using-chrooted-jail/

[5] https://linux.cn/article-8313-1.html

[6] http://blog.csdn.net/napolunyishi/article/details/21078799

作者:惨绿少年
出处:https://www.nmtui.com
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
上一篇:HTTP服务原理


下一篇:Docker、Kubernetes、Apache Mesos 之争 | 一个与传说不同的故事