|
|

楼主 |
发表于 2009-9-11 08:57:18
|
显示全部楼层

清除dmesg的内容,设置setenforce 1; setenforce 0,重新开始进程,首先运行setkey,然后运行audit2allow –d,将会显示:allow unconfined_t default_t:association setcontext;
这意味着unconfined_t尝试和default_t一起设置上下文,因为我们在SPD条目中使用了default_t,所以它是预期的结果,运行dmesg –c清除内核缓冲区,并尝试运行服务端和客户端(使用runcon):
移除不相干的规则,在客户端我们可以看到类似下面这样的规则:
allow httpd_t default_t:association polmatch;
这条规则意味着客户端(作为httpd_t运行)企图再次匹配我们之前增加的SPD条目,这个非常有用,因为你可以使用SELinux策略来强制哪个SPD条目与一个域匹配,例如:你想让一些域使用高强度的加密,而另外一些域使用更快速的,低强度的加密,那么你就可以指定哪个SPD类型与哪个域进行匹配。
allow httpd_t self:association sendto;
这条规则指出httpd_t发送数据到标记为httpd_t的团体,意味着它发送到为它创建的团体,注意目前你还不能控制哪个域发送到另一端。
allow httpd_t unconfined_t:association recvfrom;
这是最有效的控制,它告诉我们允许httpd_t接收来自一个标记为unconfined_t的团体的消息,标记为unconfined_t的团体运行在unconfined_t下,这就允许你使用策略来决定其他机器使用哪个域向你本地机器发送数据。
allow unconfined_t default_t:association polmatch;
这是在这台机器上远程域(服务端)再次匹配入站SPD条目,注意有2条SPD条目被增加进来了,一个为出站通讯一个为入站通讯,两个域分别在本地机器上(为出站)和远程机器上(为入站)匹配SPD条目。
可能会在服务端收到类似的拒绝信息,仅仅与之前的颠倒过来了,我不想重提了。使用这个技术你要做到心中有数,假设你控制了两个策略(源和目标),你非常肯定哪个域可以域机器进行通讯,哪个是跨过机器的,与SELinux IPC控制类似,但它是跨网络的。
例如:一个应用了这个技术的应用程序在雇员工作站上有一个内部和外部的浏览器,内部浏览器运行在一个域上,它允许访问公司内部包含了机密的客户信息的web应用服务器,外部浏览器可以访问internet,这就可以减少流氓internet内容泄露你内部数据的风险,这中分离的方式如果没有SELinux高级网络控制支持实现起来将非常困难(甚至是不可能实现的)。
在SELinux网络环境下同时使用IPSec和netfilter技术你将获得惊人的安全,为了更安全,你需要调式更多的信息。
值得特别感谢的是那些为这个技术努力工作的人们,将来他们会使网络架构更安全,这些人包括:James Morris, Venkat Yekkirala, Joy Latten, Paul Moore (实现了NetLabel)等
附录A:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 3490 // the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr; // connector's address information
security_context_t con = NULL;
if (argc != 2) {
fprintf(stderr,"usage: client hostnamen");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL) { // get the host info
herror("gethostbyname");
exit(1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(PORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), '', 8); // zero the rest of the struct
if (connect(sockfd, (struct sockaddr *)&their_addr,
sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
if (getpeercon(sockfd, &con)) {
perror("getpeercon");
}
buf[numbytes] = '';
printf("Received: %s from %sn",buf, con);
close(sockfd);
return 0;
}
附录B:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MYPORT 3490 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main(void)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char buf[255];
socklen_t len=254;
security_context_t con = NULL;
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order |
|