1.1 LXC是什么?
1.1.1 關於LXC
LXC,其名稱來自Linux軟件容器(Linux Containers)的縮寫,一種操作系統層虛擬化(Operating system–level virtualization)技術,為Linux內核容器功能的一個用戶空間接口。它將應用軟件系統打包成一個軟件容器(Container),內含應用軟件本身的代碼,以及所需要的操作系統核心和庫。通過統一的名字空間和共用API來分配不同軟件容器的可用硬件資源,創造出應用程序的獨立沙箱運行環境,使得Linux用戶可以容易的創建和管理系統或應用容器。
圖 - lxc官方logo
在Linux內核中,提供了cgroups功能,來達成資源的區隔化。它同時也提供了名稱空間區隔化的功能,使應用程序看到的操作系統環境被區隔成獨立區間,包括進程樹,網絡,用戶id,以及掛載的文件系統。但是cgroups並不一定需要引導任何虛擬機。
LXC利用cgroups與名稱空間的功能,提供應用軟件一個獨立的操作系統環境。LXC不需要Hypervisor這個軟件層,軟件容器(Container)本身極為輕量化,提升了創建虛擬機的速度。軟件Docker被用來管理LXC的環境。
1.1.2 關於操作系統層虛擬化
操作系統層虛擬化(英語:Operating system–level virtualization),一種虛擬化技術,這種技術將操作系統內核虛擬化,可以允許使用者空間軟件物件(instances)被分割成幾個獨立的單元,在內核中運行,而不是只有一個單一物件運行。這個軟件物件,也被稱為是一個容器(containers),虛擬引擎(Virtualization engine),虛擬專用服務器(virtual private servers)或是 jails。對每個行程的擁有者與使用者來說,他們使用的服務器程式,看起來就像是自己專用的。
操作系統層虛擬化之后,可以實現軟件的即時遷移(Live migration),使一個軟件容器中的物件,即時移動到另一個操作系統下,再重新執行起來。但是在這種技術下,軟件即時遷移,只能在同樣的操作系統下進行。
在類Unix操作系統中,這個技術最早起源於標准的chroot機制,再進一步演化而成。除了將軟件獨立化的機制之外,內核通常也提供資源管理功能,使得單一軟件容器在運作時,對於其他軟件容器的造成的交互影響最小化。
1.1.3 LXC的特點
目前的LXC使用下列內核功能來控制進程:
🏄♂️ 內核命名空間(進程間通信、uts、mount、pid、network和user)
🏄♂️ AppArmor和SELinux配置
🏄♂️ 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 系統中更改 root(chroot)是將特定用戶操作與其他 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 節點,例如 null、zero、stdin、stdout、stderr 和 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 監獄中,並且不能使用任何外部命令如(ls、date等等)。
用戶只可以執行 bash 以及它內置的命令(比如:pwd、history、echo 等等):
[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 目錄中復制進幾個用戶命令,如 ls、date、mkdir
[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