LXC,Linux containers

1 LXC安装

2 LXC的介绍

Lxc 全称,Linux containers,是一种基于容器的操作系统层级的虚拟化技术。LXC可以在操作系统层级上提供虚拟的执行环境,一个虚拟机的执行环境就是一个容器,可以为该容器绑定特定的CPU、Memory节点,并可以分配特定比例的CPU时间,IO时间,限制可以使用的内存大小(包括内存和swap空间),提供device访问控制,提供独立的namespace(网络,pid,ipc,mnt,uts);

LXC依靠Linux内核相关特性,基于容器的虚拟化技术起源于所谓的资源容器和安全容器,LXC在资源管理方面依赖与Linux内核的Cgroups子系统,Cgroups子系统是Linux内核提供的一个基于进程组的资源管理框架,可以为特定的进程组限定可以使用资源,LXC在资源隔离控制方面依赖与Linux内核的namespace特性,具体而言就是在clone时加入相应的flag(NEWNS NEWPID)等。

LXC和传统的HAL(硬件抽象层)层次的虚拟化技术相比,具有以下优势:

1 更小的虚拟化开销(LXC的诸多特性有Kernel提供,Kernel实现这些特性只有极少的消耗)

2       快速部署,不需要创建虚拟机,只需要安装LXC,不需要单独为内核打补丁。

1 Cgroups

Cgroups子系统是(control groups的缩写),是Linux内核提供的一种可以限制、记录、隔离进程组(process)所使用的物理资源(cpu,memory,io.etc)机制。

Cgroups最初的目标为资源管理器提供统一的框架,既整合现有的cpuset等子系统,也为未来开发新的子系统提供接口,现在的cgroups适用于多种应有场景,从单独的进程资源控制,到实现操作系统层次的虚拟化。

1 限制进程组可以使用资源的数量,Resource Limiting,如,memory子系统可以为进程设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会触发OOM(Out of memory).

2 进程组的优先级控制,比如,可以使用CPU子系统为某个进程组分配特定的cpu share.

3 记录进程组使用的资源数量,比如可以使用cpuacct子系统记录某个进程使用cpu的时间。

4 进程组隔离,比如使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间。

5 进程组控制,比如使用freezer子系统将进程组挂起和恢复。

Cgroups的相关概念:

1 任务:(task),在cgroups中,任务就是系统的一个进程

2 控制族群,(control groups)。控制族群就是一组按照某种标准划分的进程,Cgroups

中的资源控制是一控制族群为单位实现,一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个进程组群。一个进程组的进程可以使用cgroups以控制族群为单位分配资源,同时也受到cgroups以控制族群为单位设定的限制。

3 层级,(hierarchy).控制族群可以组织成hierarchical的形式,既一颗控制族群树,控制族群树上的子节点控制族群是父节点控制族群的孩子。继承父控制族群的特定的属性。

4 子系统,(subsystem)。一个子系统就是一个资源控制器, 比如cpu子系统就是控制cpu时间分配器的一个控制器,子系统必须附加attach到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。

Cgroups的系统相互关系

1 每次在系统中创建新层级时, 该系统中的所有任务都是那个层次的默认cgroup.(root cgroup,此 cgroup在创建层级时,自动创建,后面在该层级中创建的cgroup都是此cgroup的后代)的初始成员。

2 一个子系统最多只能附加到一个层级。

3 一个层级可以附加多个子系统

4 一个任务可以是多个cgroup的成员,但这些cgroup必须在不同的层级。

5 系统中的进程(任务)创建子进程(任务)时,该子任务自动成为其父进程所在的cgroup的成员。 然后可以根据需要将该子任务移动到不同的cgroup中,但开始时,总是继承其父任务的cgroups

Cgroups子系统介绍

blkio–这个子系统为块设备设定输入/输出限制,比如物理设备(硬盘,固态硬盘,usb等)

cpu–这个子系统使用调度程序提供对CPU的cgroup 任务访问

cpuacct– 这个子系统自动生成cgroup中任务所使用的cpu报告

cpuset –这个子系统为cgroup中的任务分配独立CPU和内存节点

devices–这个子系统允许或者拒绝cgroup中的任务访问设备

freezer– 这个子系统刮起或者恢复cgroup中的任务

memory — 这个子系统设定cgroup中任务内存的限制,并自动生成由那些任务使用的内存资源报告。

Net_cls–这个子系统使用等级识别符(classid)标记网络数据包,可以允许linux流量控制程序tc,识别从具体cgroup中生成的数据包

Ns — 命名空间子系统。

 

2 Namespaces机制

Linux Namespaces机制提供了一种资源隔离方案,PID、IPC、NetWork等系统资源不再是全局性的,而是属于特定的Namespace.每个Namespaces里面的资源对其他的Namespace都是透明的。要创建新的Namespace,只需要调用clone 时指定相应的flag。当调用clone时,设定为CLONE_NEWPID.就会创建一个新的pid Namespaces。clone出来的新进程将成为NameSpace里的第一个进程,一个PID Namespace 为进程提供了一个独立的PID环境,PID namespace内的PID将从1开始,在Namespace内调用fork,vfork,或clone都将产生一个在该Namespace内部独立的PID。新创建的Namespace里的第一个进程在该Namespace内的PID为1.PID namespace 是层次性的,新建的Namespace将会创建该Namespace的进程属于Namespace的子namespace。子namespace中的进程对于父namespace是可见的,一个进程将拥有不止一个PID。而是在所在的Namespace中的进程对所有直系祖先Namespace中都将有有一个PID。

当调用Clone,设定了Clone_NEWIPC.将会创建一个新的IPCNamespace,clone出来的进程将成为Namespace里的第一个进程,一个IPC Namespace 有一组System V IPC objects标识符构成,这个标识符有IPC相关的系统调用创建, 在一个IPC Namespace里面创建IPC object 对该Namespace内的所有进程可见,但对其他的Namespace不可见,这样就使的不同的Namespace 之间的进程不能直接通信。PID namespace和IPCnamespace可以组合起来一起使用,只需要在调用clone时,同时指定CLONE_NEWPID|CLONE_NEWIPC.

当调用Clone时,设定了CLONE_NEWNS,就会创建一个新的mount Namespace,每个进程都存在于一个mount namespace里面,mount namespace为进程提供一个文件层次视图,如果不设定这个flag,子进程和父进程共享一个mount namespace,其后子进程调用mount或umount将会影响到所有该Namespace内的进程,如果子进程在一个独立的mount namespace里面,就可以调用mount或umount建立一份新的文件层次视图。该flag配合pivot_root系统调用,可以为进程创建一个独立的目录空间。

当调用clone,设定CLONE_NEWNET,就会创建一个新的NetWork Namespace.一个network namespace为进程提供了一个完全独力的网络协议栈的视图,包括网络设备接口,IPV4/IPV6协议栈,IP路由表,防火墙规则,sockets等。一个Network namespace提供了一个独立的网络环境,就跟一个独立的系统一样。一个物理设备只能存在一个Network namespace中,可以从一个namespace 移动到另一个Namespace中,虚拟网络设备提供了一种类似管道的抽象,可以在不同的Namespace之间建立隧道,利用虚拟化网络设备,可以建立到其他的namespace中的物理设备桥接,当一个Namespace被销毁时,物理设备会自动移回init network namespace,即系统最开始的namespace.

当调用clone,设定CLONE_NEWUTS,就会创建一个新的UTS Namespace,一个UTSnamespcae 就是一组被uname返回的标识符,新的UTS namespace 中的标识符通过复制调用进程所属的namespace的标识符来初始化,clone出来的进程可以通过相关系统调用改变这些标识符,比如sethostname来改变namespace的hostname。这一改变,对namespace内所有进程可见。CLONE_NEWUTS和CLONE_NEWNET可以一起使用。

以上所有clone flag 都可以一起使用,为进程提供了一个独立的运行环境,LXC正是通过在clone时设定flag,为进程创建对立PID,IPC,FS,NETWORK,UTS的空间容器,一个容器就是一个虚拟的运行环境,对容器的进程是透明的,每个进程都以为自己直接在系统上运行。

chromium在sandbox里将设置namespace的代码:

 

Linux系统安全_PFS/ECDH

数百万网站和数十亿网民都依靠SSL保护敏感数据如密码、信用卡号码和个人信息的传输。但最近泄漏的机密文档显示,美国国家安全局会记录大量互联网流量,储存加密数据以用于以后的密码分析。美国当然并不是唯一一个这么做的国家,沙特、中国和伊朗都是如此。保留的加密数据可以通过各种方法解密,例如法庭命令,社会工程,网站攻击,乃至密码分析。如果得到了密钥,所有相关网站的历史流量可以一次性解密。这就像打开了潘多拉的盒子。然而,互联网实际上存在应对之策——密钥协商协议Perfect Forward Secrecy(PFS),如果SSL网站的私钥泄漏,PFS可以保护以前的加密流量不会因此受到影响,因为PFS可以为每次会话分配不同密钥加密通信。PFS需要客户端浏览器和服务器端同时支持才适用。–solidot.org

但问题也不止如此,当HTTPS的网站的私钥被攻破,那么攻击者便可以很容易的制造出了中间人攻击。 这便需要一种向前的保密协议。

该协议要求,今天的秘密即使在将来的密钥被泄露,而秘密也是不被泄露的。要理解这个协议,我们首先可以从经典的TLS三次握手AES128-SHA加密套件开始,在握手期间,服务器出示证书,客户端和服务器同意主密钥。

这个过程是建立在48个字节的预置密码,是由客户端使用服务器公开的密钥进行生成和加密。然后在三次握手的过程中,客户端将密钥信息交换发送给服务器。主密钥来自客户端与服务器进行hello会话的公钥与随机值。这个方案是安全,只要服务器能够对预置的密码解密(自己的私钥)客户端发送的数据。假设,攻击者记录该服务器1年内的所有客户端和服务器之间的交流数据。2年后,服务器退役,并送往循环再造,攻击者是能够恢复出磁盘驱动器的私钥。根据这个私钥,便可以对会话进行解密。攻击者依然可以恢复密码和其他敏感信息。

现在主要的问题一个事实,私钥被用于2个目的,认证服务器加密服务共享同一个密钥。认证只是在建立通信时,而加密则持续数年之久。

为了解决这个问题的方法之一便是保持使用私钥进行验证,但是要使用一个共享密钥的独立机制。Diffie-Hellam密钥交换协议,在TLS是如何工作的呢,服务器只需要生成1次:

1 P,是一个很大的素数,

2 g,是一个原根primitive root(它能生产1~P-1所有数的一个数)

3 现设g为p的原始根,则: g mod p,g^2 mod p,…g^p-1 mod p;两两互不相同,构成一个1~p-1的全体数的一个排列。

4 对于任意数b以及素数p的原始根g,可以找到一个唯一的指数i,满足b = g^I mod p,0C=i<=p-1,则称指数i为以g为底,模p的b的离散对数。

算法描述为:

假如A和B在不安全的网络上进行协商共同的密码:

因为不安全的线路上,窃听者只能得到a,p,X,Y,除非能够计算离散对数x和y,否则将无法得到密钥k,因为k是A和B独立计算出的密钥。有Xa,Xb计算出Ya,Yb容易,但反过来由Ya,Yb计算出Xa,Xb很难。安全性上基于求有限域上求离散对数的难度。

但DH算法却容易遭中间人攻击。

为了避免中间人的攻击,构造出了基于有限域上椭圆曲线之间的同源计算问题构造细腻的公钥密码系统。

假设y^2 = X^3 + ax +b,素数p和原始根g,这些参数都是公开的,事实上,它可以有服务器生成。

利用椭圆曲线是在RFC-4492中TLS延伸的部分描述的。与经典的DH交换密钥的方法不同,在客户端和服务器端需要同意各参数。完成本协议是在客户端和服务器发送hello的消息内,虽然可以定义任意一个参数,WEB浏览器将只支持少数的预定义的曲线,通常为NIST P-256,P-384,P-521.

下面简要说一下,DH的密钥交换椭圆曲线:

 

使用ECDHE-RSA-AES128-SHA加密套件(例如P-256)已经是很程度上提高了速度。也是因为DHE-RSA-AES128-SHA缩小所涉及的各种参数的规模。

但不是所有浏览器都支持椭圆曲线加密,最近的chrome和firefox支持了NIST P-256, P-384, P-521.但大多数的IE浏览器还支持的不是很好。,最近的openssl已经加入了ECDHE密码服务套件,如果要使用64位的优化本版本,需要选择OPENSSL 1.0.1,启用ec_nistp_64_gcc_128选项。

在选择套件上,ECDHE-RSA-AES128-SHA:AES128-SHA:RC4-SHA是大多浏览器所兼容的。如果要选择PFS的方式,ECDHE-RSA-AES128-SHA,DHE-RSA-AES128-SHA,EDH-DSS-DES-CBC3-SHA。但需要确保密码套件的顺序。Nginx (1.0.6/1.1.0)是ssl_prefer_server_ciphers。Apache(2.3.3)则是SSLHonorCipherOrder。

但在使用PFS的时候,也要注意服务器端定期更新所生成的随机密钥。

Openssl的检测使用指令:openssl s_client -tls1 -cipher ECDH -connect 127.0.0.1:443

Nginx 关于PFS的代码:

使用RSA算法的时候,产生一个临时的DH密钥磋商发生,这样会话将根据这个临时的密钥加密。而证书中的密钥作为签名。这样增加了安全性。

该方法实现了OPENSSL提供的默认DH_METHD,实现了根据密钥参数生成DH公私钥,以及根据DH公钥(一方)以及DH私钥(另一方)来生成一个共享密钥,用于密钥交换。

ECDH参数不完全和DH一样,对与DH所产生参数是一个耗时的过程,所以服务器允许通过外部文件加载DH参数。ECDH的参数的形成是一套硬编码的曲线,所以参数的形成只是寻找他们,当服务器使用时,便可以加载他们。但在openssl1.0.2之前是不支持的。

可以做的是,提供ECDH参数从一个文件里读取,为了一个共同的组的一个后备。P-256是一个不错的选择则。

而这个设置不需要在服务器端进行设置,而使用的参数是有服务器端指定。

Linux系统安全_sandbox_seccomp-bpf

        linux3.5以后linux支持了Will Drewry的Seccomp-BPF的特性。Seccomp-BPF是建立在能够发送小的BPF(BSD Packet Filter)程序,有内核来执行。这个特性起先源于tcpdump的设计,因为性能的原因,可以直接在内核中运行。BPF相对与内核是不可信的,因此, 限制了有限的数量。值得注意的是,他们不能循环,限定单一函数的执行时间,以及大小,并允许内核知道他们的永远终止。

BPF(BSD Packet Filter)是一种用于Unix内核网络数据包的过滤机制。Linux之前包过滤LPF。Linux随着版本的不同,所支持的捕获机制也有所不同。2.0之前的内核版本,对Socket使用类型SOCK_PACKET,调用形式是Socket(PF_INET,SOCK_PACKET,int proctol),但这种用法已经过时,2.2之后,提出的一种新的协议簇,PF_PACKET来实现捕获机制,调用形式为:socket(PF_PACKET, int socket_type, int protocol),其中socket类型可以是SOCK_RAW,和SOCK_DGRAM,SOCK_RAW 类型使得数据包从数据链路层取得后,不做任何修改,直接传递给用户数据,而SOCK_DGRAM,则要对数据包进行加工(cooked),把数据包的数据链路层头部去掉,而使得一个通用结构sockaddr_ll来保存链路信息。

使用2.0版本内核捕获数据包存在多个问题,首先,SOCK_PACKET方式使用结构sockaddr_pkt来保存数据链路层信息,该结构缺乏包类型信息;其次,如果参数MSG_TRUNC传递给读包函数recvmsg, recv, recvfrom 等,则函数返回的数据包长度是实际读到的包数据长度,而不是数据包的真正长度。

PF_PACKET方式规避上以上的问题,在实际应用中,用户程序显然希望直接得到“原始”数据包,因此使得SOCK_RAW类型最好。Libpcap使用的SOCK_DGRAM.从而也必须为数据包合成一个“伪”链路层头部(sockaddr_ll).1,某些类型的设备数据链路层头部不可用,例如linux 内核的ppp协议,实现代码对ppp数据包的支持的不可靠,2在捕获设备为any时,所有设备意味着libpcap对所有的接口进行捕获。需要要求对所有数据包有相同的数据链路头部。具体的详细描述:http://www.linuxjournal.com/article/4852

    BPF是一种过滤机制,有网络阀(Network tap)和过滤包组成,网络阀用于从网卡设备驱动处收集网络数据包拷贝,并负责向已注册监听的用户态应用程序递交数据,过滤器则是用于决定收集的网络数据是否满足过滤器要求,满足条件的则进行后继的拷贝工作,否则丢弃该数据。

    该图的过程为:当数据包到达网络接口时,链路层的设备驱动程序通常是将数据包直接传送给协议栈进行处理。而当BPF在该网络接口注册监听时,链路层驱动程序将数据包传送给协议栈之前,先会首先调用BPF。BPF负责将此数据包指针传递至每个监听进程指定的内核过滤器,这些用户自定义的过滤器决定数据包是否被接受,以及数据包中的那些内容将被接受,对于每一个决定接受数据包的过滤器,BPF此时才进行数据拷贝工作,将所需的数据拷贝至于过滤器相连的缓冲区中,以供用户监听进程读取。数据拷贝结束后,网络设备驱动程序重新获得系统控制权,系统进行正常的网络协议处理。我们注意到BPF是先对数据包过滤,在缓冲,避免了类似SUN的NIT过滤机制,先缓冲每个数据包直到用户读取数据时在过滤造成的效率问题。

    BPF 的设计思路和当时的计算机的硬件发展有大关系,相对较老的CSPF(CMU/Stanford Packet Filter)它有两大特点,1 :基于寄存器的过滤机制,而不是早期的内存堆栈过滤机制,2:直接使用独立的,非共享的内存缓冲区。同时,BPF在过滤算法上也有很大进步(有人也做了一些优化BPF+),它使用了无环控制流图(CFG,control flow graph).而不是老式的布尔表达式树(Boolean expression tree)。

下面说一下BPF的包过滤模式:

    包过滤可以看作是针对数据包的布尔函数运算。如果返回值为真,那么内核为监听程序拷贝数据,反之则丢弃。形式上包过滤由一个或者多个谓词判断的AND操作和OR操作组成。

    包过滤在具体的实现上是通过将数据包简单的看作一个字节数组,谓词判断根据具体的协议映射到数组的特定位置进行判断过滤工作。例如,判断数据包是否是ARP协议,只需要盘点数组的第13,14个字节是否为0×0806。因此,包过滤的算法的中心任务,是使用最少的判断操作。

    布尔表达式树理解上比较直观,它的每一个叶子结点即一个谓词判断,而非叶子结点则为AND或OR操作。而CFG算法是一种特殊的状态机,图中每一个非叶节点代表的是对数据包进行谓词判断操作,而边则是判断的结果。在CFG中,只存在2个叶子结点,分别代表过滤通过True和未通过Flase。
CSPF主要有3个缺点,1:过滤操作使用的栈在内存中被模拟,维护栈指针需要使用若干的加/减等操作,而内存操作时现代计算机架构的主要瓶颈。2:布尔表达树造成了不需要的重复计算。3不能分析数据包的变长头部。BPF使用的CFG算法,实际上是一种特殊的状态机,每一个节点代表了一个谓词判断,而左右分别对应了判断失败和成功后的跳转,跳转后又是谓词判断,这样反复操作,直到到达成功或失败的终点。CFG算法的优点在于把对数据包的分析信息直接建立在图中。从而不需要重复计算。CFG是一种“快速的,一直向前”的算法。

BPF包过滤模式的实现,BPF采用了一种过滤器伪机的方式(filter Pseudo-machine)。BPF伪机器方式是一个轻量级,高效的状态机。对BPF过滤代码进行解释,BPF过滤机过滤代码形式为”opcode jt jf k”,分别代表了操作码和寻址方式,判断正确的跳转和失败的跳转,以及操作所使用的通用数据域。

    BPF过滤代码从逻辑上看,很类似汇编语言,但它实际上是机器语言,注意到上述的3个域的数据都是int和char型。显然,有用户来写过滤代码太过于复杂,但这种设计更适合用于操作硬件。特别用来编写需要写少量固定序列的硬件驱动程序。BPF实际上是一组基于状态机匹配的过滤序列,用于简单的数据包模式匹配。用指令集简单的将上图描述如下:

    每个匹配包至少包含4个元素,定义为一个结构体如下:

    其很显然应该是一个状态驱动的循环:

看看linux实现的代码,基本上是这样实现的。

    BPF用于很多的抓包程序,在linux中,一般内核自动编译进了af_packet这个驱动,因此只需要在用户态配置一个PACKET的socket,然后将filter配置进内核即可,使用setsockopt的SO_ATTACH_FILTER 命令,这个filter是在用户空间配制的,比如tcpdump应用程序,tcpdump和内核BPF过滤器的关系类似iptables与netfilter的关系,只是Netfilter实现了match/target的复合配合,而BPF的target则只是选择是否要与不要。

    回到主题上来,seccomp-bpf在使用BPF的时候,借鉴了其思想。
大量的系统调用暴露在用户空间,在程序的整个生命周期内并没有使用。而随着系统调用的改变和成熟,bug的发现和根除,一套可用的系统调用是满足用户程序基本的调用。将可以产生出一组尽量少的系统调用暴露在用户空间。系统调用的过滤就是在应用程序的使用中。

Seccomp过滤器提给了一种手段,为一个进程调用系统调用时指定了过滤器,而这个过滤器则是BPF。BPF作为socket过滤器不同之处则是操作当前的user_regs_struct数据结构,这需要预先定义好系统调用的ABI和定义过滤规则。但系统调用的参数保存在用户空间,但要验证该参数是否安全是非常困难的。

    Seccomp用户无法避免TOCTOU (time-of-check-time-of-use)系统调用对框架的注入式攻击。如一个恶意进程可能会在“参数被安全检查”之后,而在实际使用之前,将参数换掉,这边使节或系统调用时所作的参数检查变得没有意义。但要解决这个问题,也不能仅把目光盯住系统的调用入口。

针对系统调用的过滤,不是一种沙箱的模式,其更多的提供了减少内核暴露的表面,除此之外,需要和其他的规则和方案进行配合。
当seccomp模式被添加,但它们不是直接设置超时的过程,是一种新的模式, 仅当CONFIG_SECCOMP_FILTER设置,并用prctl启用PR_ATTACH_SECCOMP_FILTER参数。
与seccomp过滤器交互式通过prctl调用。
PR_ATTACH_SECCOMP_FILTER ,允许一个新的过滤器使用BPF程序的规范,BPF程序将被执行user_regs_struct结构的数据。用法为

Linux系统安全_Sandbox

Sandbox沙箱在计算机领域中是一种程序隔离的机制,其目的则是限制不可信进程的权限。沙箱技术则常用于执行未经测试的或不可信的客户程序,(比如沙箱杀毒一类的),为了避免不可信程序可能破坏其他的程序运行,沙箱技术可以为不可信的程序提供虚拟化的磁盘,内存以及网络资源,而这又是对客户是透明的。

常规的安全机制则主要以降权来解决问题,但降权并不能带来真正的安全,sandbox也不能带来全方位的安全,沙箱机制结合多种系统安全技术来实现安全,从设计的理念上,打破传统的单一防御到纵深防御。

常规的纵深防御有六种常见的手法:

1 安全的编码(Secure Code),减少编写的错误。

2 应用技漏洞缓解技术(Application-level exploitation)(SSP,relro)

3 系统级漏洞缓解技术(System-level exploit mitigation)(ASLR,NX),

4 降权处理(Privilege Dropping)(Sandboxing)

5 强制访问控制(Mandatory access control)(MAC,SELinux)

6 更新策略(Update strategy)

 

进程和权限

         1 每个进程拥有独自的地址空间

         2 MMU硬件强制分离地址空间

         3 内核在系统中有强制性的接口层(kernel的安全策略)

         4 每个进程拥有进程权限边界

         5 root用户拥有至高的权限

         6 其他用户拥有自主访问控制DAC访问权限

一般情况下的权限控制为:

         进程A拥有的权能比进程B拥有的多,则A可以获得B进程可以访问的资源

         1 root用户运行任何程序都是特权用户

         2 2个进程如果拥有相同的uid,和gid。则可以拥有相同的权限

         3 一般不能比较不同uids用户的进程权限

进程和权限的分离

         1 线程

                   将内部特权进行分离(一般情况下)如NaCI,SECCOMP Sandbox

         2 Debugging

                 如果A进程可以Ptrace()B,那么A的权限要大于B的权限

 

 Linux标准的权限资源有

         1 Users,和 groups

                   1 uid,euid,suid,fsuid

                   2 gid,egid,sgid,fsgid,超级组

         2 POSIX.1e 权能

         3 Quota control

         4 Linux Container

         5 LSM(Linux Security Module)

 

Linux的权能划分了不同的权限单位

         如:CAP_NET_RAW: 允许使用RAW和PACKET Socket

                   CAP_SYS_ADMIN: 管理员操作权能(mount,sethostname等)

                   CAP_NET_BIND_SERVICE:bind绑定端口权限<1024

 

 权能的限制

         1 常见的误区:

                   1 忘记切换uid 为0的超级用户。很多功能需要root用户的权能

         2 root 操作

                   1 只有用到root权能的时候,才将权限提升为root权限

                   2 很多操作只需普通用户的权能。

使用切换root

1         需要对文件系统进行权限控制的时候,需要root用户

2         只有root可以操作的活动

3         需要一些陷入或escape的权限时,需要流行的chroot技术。

4         模块注入 非chroot进程的ptrace()

 

新的命名空间(Namespaces:CLONE_NEW*)

         CLONE_NEWPID: New pid namespace(2.6.24)

         CLONE_NEWNET:New network namsespace(2.6.26)

         CLONE_NEWIPC,CLONE_NEWUTS,CLONE_NEWNS(2.6.19)

 

资源限制

         为了安全的资源限制机制

         1 RLIMIT_NOFILE:不能获得新的句柄,但可以rename或者unlink

         2 RLIMIT_NPROC: 不能创建新的进程

         如果为了安全,RLIMIT_NPRC需要设置为(0,0),因为一些攻击者可以替代已经存在的句柄去创建新的socket或者文件句柄。

 

Dumpable(Debuggable)进程

         Linux支持对每个进程进行dumpable标志。

          通过PR_SET_DUMPABLE标记设置prctl,跟踪执行你没有权限的程序,或者切换uid。

          一个进程没有CAP_SYS_PTRACE权能,是不能ptrace非dumpable的进程

         需要一个进程权限提升或者可以降低其他进程的权限来满足dumpable。

 

MAC强制的访问控制

         在内核机制中,基于LSM钩子的有,SELInux,SMACK,TOMOYO

         内核机制之外的有:GRSecuirty, RSBAC, AppArmor

 

Sandbox 采取权限限制的策略

Sandbox与MAC的区别

         MAC需要管理员去分发布商。每个程序需要一套单独的规则库,不需要对代码的控制权

         Sandbox则是面向开发者,每个程序可以运行在多个设备上,不要要设备管理员的权限

 

常见的sandbox的设计:

         1 ptrace() sandbox (vsftpd)

         2       setuid sandbox(chromium)

         3      SECCOMP sandbox(chromium)

1 ptrace 架构:

setuid sandbox

 setuid sandbox基于Linux Kernel 所提供的安全机制如DAC实现,利用了uid/gid +  chroot()+capability的组合来达到目标,实现起来相对较为简单。

         传统的root 很难避免以下问题:1 需要对文件系统删除的访问2 RLIMIT_NOFILE 不够时的处理3  防止其他进程ptrace 4阻止信号发送给其他进程。

(一) Setuid :

利用uid的切换工作:

1我们需要获取uid/gid的定义池,但不需要资源/etc/passwd

2调用时,搜索到未用的uid/gid.然后切换到这个uid/gid

3执行sandbox。

Linux uid/gid 机制主要是用于进程的权限隔离,当你要执行不可信的程序时,那么在启动该程序的时,为其分配一个random uid。然后设置setuid。工作流程如下

Fork() ->setuid()->{设置相关的进程资源限制,如RLMIT_NPROC(0,)}->execve();

Setuid() 需要root的权限(或者具有CAP_SETUID 权能)才能调用成功。

 

(二) Chroot:

chroot 是 linux kernel 的另一个安全功能,他主要用于修改进程的根目录,比如执行chroot(“/tmp/sandbox/1”)则可以将当前进程的根目录切换为”/tmp/sandbox/1”。那么该进程的文件操作权限则被限制在当前目录下。

Chroot需要root权限(或者具有CAP_SYS_CHROOT权能)才能调用成功。

如果按照前面执行的顺序,具有root权限的进程A去执行chroot,然后再调用setuid,->..->execve(),这样是不可以的,因为execve所执行的路径已经发生改变,可执行文件已经不存在了。

Chris Evans的文章给了一个解决方法:

 

对A程序来说,由于它是以Root身份运行,那么就可能作为攻击点,比如confuesed deputy问题。下面针对这个问题加以说明。

 

(三) Linux Capability

 主要解决confused deputy问题,这个问题典型的代表是跨站点请求伪造(CSRF)。

Linux支持Capability的主要目的则是细化root特权,避免confused deputy问题。比如ping这个命令,需要raw_sockets,所以需要root的权限才可以运行,如果有了Capablity机制,该程序只要一个CAP_NET_RAW的权能,便可以运行,根据最小权限原则,该程序可以去掉所有不必要的权能。

当前kernel支持的权能多大30多种。在kernel2.6.24以后,普通用户也具有了capability.

 

Setuid sandbox简单易行,在google chromuim  早期的沙箱机制中使用了它,但现在已经默认为seccomp机制了。利用ipc机制创建socket pair

Seccomp

Seccomp 是 Andrea Arcangeli在2005年设计的,其目的则是解决 grid computer中的安全问题,比如你打算租借cpu资源,但又担心不可信的代码会破坏你的系统,那么seccomp

则为你提供了一个“安全(SAFE,not SECURE)”的环境。

         内核从2.6.10开始引入seccomp机制,该机制限制系统调用为read(),write(),exit(),sigreturn(). 只有4个系统调用被允许,相对较为简单,其限制了不能分配内存,不能共享内存, 不能创建新的文件描述符。成为了一个纯计算型的代码。

  运行在seccomp机制下的线程成为可信线程,当不可信的线程请求可信线程进行系统调用时,可信线程验证后方可进行调用。可信线程也只能使用只读的存储器,不能读取可变的区域。

有人提出了对seccomp机制的改进,利用bitmap增加一个新的mode,来限制使用那些权能。

通过截获系统调用来实现sandbox是一贯的做法,在现在的操作系统中,用户空间和内核空间是隔离的,一个进程只能通过系统调用才能从用户空间进入内核空间,如果一个进程不执行系统调用,那么被攻击的风险便会降低。当然,不调用系统调用是不切合实际的。

针对chromium使用的sandbox机制,我们将接下来进行分析。

Linux系统管理_iptables

1 概述

 防火墙的应用在linux操作系统中及其常见,本文省去一些简单的技术介绍,直接进入主题介绍防火墙的一些深度知识。

2 防火墙的基本概念

 防火墙的任务简单的描述就是放行合法,或封锁不合法的封包,关于什么是防火墙这里就不做介绍了。

2.1 防火墙的判别依据

各层封装包包头信息:

1 链接层信息:

获取连接层信息不是很难:如:

我们使用tcpdump扑捉信息:

从所显示的内容,最为重要的莫过于MAC address,我们可以在防火墙的过滤规则中借助Destination MAC来判别封包是有那个主机发过来的。
2 网络层
获取网络层的主要为IP包头,其包头有很多可用信息是可以作为过滤条件的。

从上图可以得到一些我们想要的信息:
0×0000 代表IP包头
4500 0048 9e44 4000 4011 194b c0a8 00c4
这段信息分别表示:
4500;4代表ipv4,5代表IP包头长度为5个32bit(32bit也就是4个字节)00代表TOS(000 0000 0)前3个bit的优先权,现已忽略,4bit的TOS分别为最小延时,最大吞吐量,最高可靠性,和最小费用
0048-总长度(数据包总长度:头部 + 数据长度)
9e44;代表唯一标示符
4000;代表不分片,其是标识字段,和片偏移
4011;40代表生存时间TTL,11(上层协议号,11upd,6tcp 255 RAW)
194b;代表校验值。
Coa8 00c4 代表 SRC IP,源IP,可以inet_ntoa转换成点号分隔的IP。
0×0010: c0a8 0101
coa8 代表目标IP。
3 传输层

传输层可以获取的信息有很多,如端口号,tcp长度,flags标准为等。
防火墙的分类:
包过滤防火墙,应用层防火墙,
常见的防火墙结构:
单机防火墙,网关式防火墙,通透式防火墙
这里简单的介绍一下通透式防火墙,通透式防火墙就是一个bridge设备,并且在bridge设备上赋予filter的能力,因为bridge是工作于OSI第二层的网络设备,因此不会有任何Routing的问题,并且Bridge上不需要指定任何IP,这样没有“Routing”的问题,防火墙主机本身无须指定IP。因此,通透式防火墙的部署能力也是相当强。

3 防火墙命令结构

Netfilter分为4个Table,分别为Filter,NAT,Mangle,以及RAW。
Table Chain
Filter          INPUT,FORWARD,OUTPUT
Nat              PREROUTING,POSTROUTING,OUTPUT
Mangle      PROROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
RAW          PREROUTING,OUTPUT
Filter:Filter是netfilter内最为重要的机制,其任务为执行封包的过滤动作,也就是防火墙的功能;
NAT(Network address Translation)也是防火墙不可或缺的重要机制,其主要功能通俗的说就是IP分享器。
Mangle;Mangle是一个特殊的机制,可以借助Mangle修改行径防火墙内的封包,
RAW :负责加快封包穿越防火墙机制的速度,借此提高防火墙的功能。

在做防火墙策略的时候,要为每个Chain准备一个Default Policy,不管Chain有多少规则,Default Policy永远在每个Chain的低端。
当一个封包进入INPUT china之后,Filter机制即会以这个封包的特征从INPUT china之内的第一条规则逐一的向下匹配,匹配的规则方式为“irst match” 即所谓的“优先执行”。
我们常听说Linux防火墙叫做Iptables,其实这样的称法是不正确的,那么Iptables是什么呢,Netfilter所需要的规则是填写在内存里,但问题是防火墙管理人员如何将规则填写到内存呢,因此管理人源需要一个规则编辑工具,通过这个工具来对内存的规则进行新增,修改和删除,这个编辑工具就是iptables以及ip6tables。
Netfilter的支持的模块越多,防火墙的功能也就会越多,而且我们可以借助升级Kernel的方法达到顺便升级Netfilter的目的,不过防火墙升级不单单是升级kernel就可以解决的,也并非一味增加netfilter模块就可以无限扩充Netfilter的功能,我们知道管理人员借助iptables工具,把规则填写到netfilter的规则数据库中,而这里就需要特定的语法,我们将规则给iptables交给iptables工具时,iptables工具会首先检查语法是否正确。但iptables是怎么获得新模块的语法结构呢。
实时上iptables 也有模块,这些模块放在/lib/iptables目录下。fc16的结构有点变化,为:

下图为iptables访问的流程图

防火墙的规则不在这里细说了,本文主要涉及的是理论上的基础知识。这里介绍以下对外建立链接时的问题

4 解决无法在防火墙主机上对外建立链接的问题

在常规模式下,客户端必须使用大于1024的端口,如果将大于1024的端口都打开,对于防火墙的限制原则是无法接受的,在netfilter/iptables里使用了“链接追踪”的功能,这个功能有x_state.ko模块所提供。
X_state.ko在iptables叫做state,我们 知道在TCP/TP 规范中,链接状态为12中,这12种分别为:ESTABLISHED、SYS_SENT、SYN_RECV、 FIN_WAIT1、 FIN_WAIT2、 TIME_WAIT、 CLOSED、 CLOSE_WAIT、 LAST_ACK、 LISTEN、 CLOSEING、 UNKNOWN。 这12种状态在TCP的三次握手和四次断开中经常使用,而state模块只有4中状态,分别为ESTABLISHED,NEW,RELATE,INVALID。这4个状态和TCP/IP的12中状态不能混为一谈,因为两者是完全不相关的定义,例如在TCP/IP标准状态描述下,UDP和ICMP封包是没有链接状态的,而在state模块下是有链接状态的。

4.1 ESTABLISHED


我们看到上图有一个这样的例子,第一个链接为TCP封包的关系,第二个为UDP封包的关系,第三个则是ICMP封包的关系,这里简要介绍这三种关系。
TCP封包关系:客户端执行ssh client,对网络上的ssh server发起访问请求,这是送出的第一个封包就是服务器请求的封包,如果这个封包能够成功穿越防火墙,那么接下来的1,2的方向所有封包的状态都是ESTABLISHED。
UDP封包关系,firefox请求访问服务,firefox首先请求DNS解析服务,firefox会想DNS发送一个封包,以请求名称解析,如果能够通过防火墙,则在3,4方向的所有封包的状态都是ESTABLISHED。
ICMP封包关系。客户端提出ping请求,ping发送一个ICMP封包给服务器,如果这个封包能够通过防火墙,则在5,6方向的所有封包状态都是ESTABLISHED。
综上所述,只要封包能够成功穿越防火墙,那么之后所有封包的状态,包括反向所有的封包状态都是ESTABLISHED。
解决这个问题的方法,则是有state模块的ESTABLISHED状态。
如:

4.2 NEW

NEW与协议完全无关,其所指的是每一条链接中的第一个封包,他是指一条连接中SYN=1的那个封包,在链接中,第一个封包主要用来做安全处理。

4.3 RELATED

RELATED是指被动产生的响应封包,而且这个封包不属于现有的任何链接的封包。

上图为traceroute的一个实验,当 192.168.0.1收到封包后,将封包的TTL值减1,并发送给主机一个ICMP协议的数据包,将数据包传给下一个主机192.168.1.1,如此类同,而传给服务器的那个ICMP封包的状态是RELATED。
这里需要说明的是,RELATE与协议无关,只要回应来的封包是因为本机先送出去的一个封包导致另一个连接产生,而这一条新链接上的所有封包都属于RELATED状态的封包。

4.4 INVALID

INVALID状态是指状态不明的包,不属于上面三种状态,因此一般视这种状态为恶意软件包,DROP掉。

5 Netfilter/iptables 高级技巧

iptables的基本规则这里就不多讲了,互联网上这方面资料是很全面的,在写完策略的时候,注意对策略的优化,防火墙的匹配规则从上至下,写策略要把握好一个原则就是:
越热门(匹配命中次数越高者)规则越写在前面,不过有时候我们难衡量那个服务也比较热门,netfilter设计了一个统计功能

Netfiler的2个模块,multiport模块和iprange模块。
multiport模块将分别对应的端口数在一个规则里表示出来,这样每个服务所需要的匹配数都是一样的。
Iptables -A INPUT -p all -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp –syn -m state NEW \-m multiport –dports 22,23,25,80,110 -j ACCEPT
iprange模块是将规则中的一段IP区域开放,使用iprange可以精简为一条规则
IPTABLES -A INPUT -m iprange –src-range \10.2.20.20-10.2.20.100 -j ACCEPT
如果防火墙后门有很多主机,如果我们对一个主机配100个规则,那么就会有300个规则,这样如果有一个封包需要匹配最后一条,这样就会有299条无效的匹配。这时候可以使用User Define Chain方法。User Define Chain方法是指用户可以自己定一个和INPUT,FORWORD,OUTPUT一样的Chain。
可以使用iptables —N NAME 来新增策略。如过对后面3个主机设置策略,按照IP协议来分,就可以分为 10.2.20.160 Chain,10.2.20.161 Chain.以及10.2.20.162Chian.
在优化策略的时候,没有一定的标准,也没有正确的答案,只要能够让整体防火墙的无效匹配次数降到最低,那么这就是我们想要的。

5.1 RAW

本节将说一下RAW表,如果系统加载了ip_conntrack模块,任何穿越防火墙的链接都会记录在/proc/net/ip_conntrack文件内,但有时候,我们不一定需要记录每一条链接信息。如果我们的规则如下

这时候,ip_conntrack会自动追踪所有链接,那么我们怎么考虑不去追踪某一个链接呢,RAW就派上用场了。

RAW table 所带来的好处就是加速,以及增加可追踪的链接数量,因为被RAW Table定义的链接是不会被追踪的,因此,也就不会占用任何的链接追踪数量,此外,RAW TABLES 所定义的链接会直接跳过NAT TABLE 及 ip_conntarck模块,因此可以加速进入防火墙封包的速度,但所定义的链接也会跳过NAT TABLE,所以RAW TABLE定义的连接都无法被NAT 机制所处理。
RAW TABLE 拥有2个Chain,分布为PREROUTING ,OUTPUT .
PREROUTING Chain 如果是网关式防火墙,则PREROUTING Chain可以用来处理防火墙两侧网络之间所建立的链接,因为这些封包都会经过PRERROUTIN Chain,另外也可以处理任何主动链接主机的连接。
OUTPUT Chain 类似NAT TABLE 的OUTPUT chain ,但是PREROUTING Chain无法处理任何有防火墙对外建立的链接,RAW 设计了一个OUTPUT chain。
防火墙的高级应用主要为通信协议的处理,简单的协议和复杂的协议,如FTP,PPTP,H.323 SIP等。