梅苑
- 关注
八、备份策略
8.1安全需求
有些医院独立研发的药品的研究信息,药品成分等信息需要定期备份防止丢失
8.2安全实现
打开任务计划程序->创建任务
设置任务
成功部署
九、部署FTP服务器
9.1安全需求
有些医院独立研发的药品的研究信息,药品成分等信息需要存放到FTP服务器上以保证信息不被丢失
9.2安全实现
下载了网络空间安全2018大群的ftp服务器使用
设置好用户为cumtmeiyuanshashou,密码为CUMTmeiyuanshashou@
指派权限为下载上传和新建目录
使用客户机链接此ftp服务器,并成功传输文件
十、PKI设置
10.1安全需求
医院内部提供证书申请服务,域中用户可以从域控申请数字证书,从而完成安全CA认证,防止中间人攻击
10.2安全实现
打开 mmc 管理器,添加证书
选择 EFS 恢复代理
至此证书申请成功,根 ca 证书
web 页面客户机申请添加证书
打开客户机访问根域的 http://192.168.111.131/certsrv
安装证书
组策略结合 CA 服务器来完成证书的自动注册申请,利用这种方式,我们可以对整个域的用户或某个组织的用户,只要用户在开机后以域用户身份登录,就可以自动完成证书的注册申请MMC 中添加证书模板单元
复制模板
配置组策略
SSL 使用,IIS 中添加签名证书
申请证书
发现成功创建
客户机登录证书 http://192.168.111.131/certsrv
IIS 管理器,点击完成证书申请成功添加证书
在 IIS 里面点击绑定,找到 https 类型,设置 ssl 证书为刚才新添加的证书
然后我们重新绑定一致的网站
十一、医院与附属子医院实现IPSec通信
11.1安全需求
CUMT医院本部与CUMT附属医院之间两台域控之间实现加密会话
11.2安全实现
编辑组策略,创建 ip 安全策略
设置名字
添加筛选表
设置源 ip
设置目标 ip
设置协议类型
设置筛选器向导
设置加密
设置身份验证方法为预共享密钥
分配
Ps:记得在两台域控都要设置
在策略指派前与主机不能 ping 通
在两端策略指派后与主机能 ping 通
十二、部署战略性蜜罐系统(模拟护网蓝队)
12.1安全需求
假如CUMT医院成为了护网行动的首要攻击对象,上级教育部要求部署一定的溯源防御蜜罐系统
12.2蜜罐工作原理
HFish由控制端和节点端组成,控制端用来生成和管理节点端,并接收、分析和展示节点端回传的数据,节点端接受控制端的控制并负责构建蜜罐服务。
融合在企业网络中
12.3文件结构
12.4蜜罐部署
我们为域加入一台linux作为蜜罐管理端
下载并部署部署蜜罐
添加蜜罐模板
将此模板部署到内网系统中,生成节点
将节点exe文件通过共享文件夹的方式共享到整个域中
根域节点上线(192.168.111.131)
子域节点(192.168.111.131)上线
链接模板部署蜜罐客户机系统
12.5模拟真实攻击
12.6成功溯源
监听浏览、统筹管理
十三、常见内网攻击的防御(模拟护网蓝队)
13.1安全需求
假如医院域内某台主机已经被黑客操控,现在内网已经很不安全,要求蓝队人员对域控服务器加固,防止黑客进一步横向移动渗透,防止黑客窃取凭据,从而威胁整个医院的安全
13.2攻击机与域模拟真实分配部署
模拟内网渗透,所以直接将攻击机kali(192.168.111.130)加入内网,并为客户机上线一台cs马,来模拟黑客已经攻陷一台内网电脑
域控192.168.111.131
子域控192.168.111.133
13.3模拟内网信息搜集
使用hashdump获取凭据
Mimikatz
13.4模拟黄金票据攻击
黄金票据是伪造票据授予票据(TGT),也被称为认证票据。如下图所示,与域控制器没有AS-REQ或AS-REP(步骤1和2)通信。由于黄金票据是伪造的TGT,它作为TGS-REQ的一部分被发送到域控制器以获得服务票据
Kerberos黄金票据是有效的TGT Kerberos票据,因为它是由域Kerberos帐户(KRBTGT)加密和签名的 。TGT仅用于向域控制器上的KDC服务证明用户已被其他域控制器认证。TGT被KRBTGT密码散列加密并且可以被域中的任何KDC服务解密的。
黄金票据的条件要求:
1.域名称[AD PowerShell模块:(Get-ADDomain).DNSRoot]
2.域的SID 值[AD PowerShell模块:(Get-ADDomain).DomainSID.Value]
3.域的KRBTGT账户NTLM密码哈希
4.伪造用户名
一旦攻击者拥有管理员访问域控制器的权限,就可以使用Mimikatz来提取KRBTGT帐户密码哈希值。
黄金票据条件充足
13.5模拟蓝队针对攻击做出防御
此时蓝队防御者通过查看票据发现异常,对此做出防御
1.限制域管理员登录到除域控制器和少数管理服务器以外的任何其他计算机(不要让其他管理员登录到这些服务器)将所有其他权限委派给自定义管理员组。这大大降低了攻击者访问域控制器的Active Directory的ntds.dit。如果攻击者无法访问AD数据库(ntds.dit文件),则无法获取到KRBTGT帐户密码。
- 禁用KRBTGT帐户,并保存当前的密码以及以前的密码。KRBTGT密码哈希用于在Kerberos票据上签署PAC并对TGT(身份验证票据)进行加密。如果使用不同的密钥(密码)对证书进行签名和加密,则DC(KDC)通过检查KRBTGT以前的密码来验证。
3.建议定期更改KRBTGT密码(毕竟这是一个管理员帐户)。更改一次,然后让AD备份,并在12到24小时后再次更改它。这个过程应该对系统环境没有影响。这个过程应该是确保KRBTGT密码每年至少更改一次的标准方法。
4.一旦攻击者获得了KRBTGT帐号密码哈希的访问权限,就可以随意创建黄金票据。通过快速更改KRBTGT密码两次,使任何现有的黄金票据(以及所有活动的Kerberos票据)失效。这将使所有Kerberos票据无效,并消除攻击者使用其KRBTGT创建有效金票的能力。
我这里尝试快速更改KRBTGT帐号密码2次
防御成功:
实现的安全需求汇总
密码策略:
密码必须符合复杂性要求
密码长度最小值6
密码最短使用期限0天(为了方便可以随时更改密码)
密码最长使用期限60天(为了安全性强制用户每两个月更换一次密码)
记录五个历史密码
可以用还原的加密来存储密码
用户无操作30分钟后锁定账户
五次无效登陆后锁定用户
30分钟之后重置账户锁定计数器
服务票据最长寿命300分钟
时钟同步的最大容差5分钟
强制用户登录限制
用户票证最长续订最长寿命10天
用户票证最长寿命10小时
为了防止下层管理员组织域全局策略,需要设置策略为强制
允许医生、护士、员工周一到周五登录用户
允许院长、主任、护士长周一到周日登录
允许保安队队长、员工周一到周日登录
添加各个部门的用户到对应的全局组
将全局组添加到域本地组(采用AGDLP原则)
让院长对所有域本地组委派权限
让各个主任对所管理的部门用户所在的域本地组委派权限实现统筹管理
搭建一个CUMT医院的主页部署到医院购买的云服务器(http://47.97.231.88)
对医院内所有电脑设置IE浏览器默认主页为CUMT医院的主页97.231.88
医院内所有用户都使用矿大壁纸
为医院内所有用户分发软件
为医院内所有用户配置登录注销脚本
搭建一个CUMT医院的主页部署到医院购买的云服务器(http://47.97.231.88)
对医院内所有电脑设置IE浏览器默认主页为CUMT医院的主页97.231.88
医院内所有用户都使用矿大壁纸
为医院内所有用户分发软件
为医院内所有用户配置登录注销脚本
使用exchange server作为邮件服务器在医院内部部署
由于保安部门的特殊性,保安部门的用户的电脑主要要用来监控录像,所以需要对保安部门设置强硬的软件限制策略,并设置为强制
有些医院独立研发的药品的研究信息,药品成分等信息需要存放到FTP服务器上以保证信息不被丢失
医院内部提供证书申请服务,域中用户可以从域控申请数字证书,从而完成安全CA认证,防止中间人攻击
CUMT医院本部与CUMT附属医院之间两台域控之间实现加密会话
假如CUMT医院成为了护网行动的首要攻击对象,上级教育部要求部署一定的溯源防御蜜罐系统
假如医院域内某台主机已经被黑客操控,现在内网已经很不安全,要求蓝队人员对域控服务器加固,防止黑客进一步横向移动渗透,防止黑客窃取凭据,从而威胁整个医院的安全
附录
Web前端程序架构如下:
index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>CUMT医院预约平台</title>
<link rel="stylesheet" type="text/css" href="css/base.css" />
<link rel="stylesheet" type="text/css" href="css/layout.css"/>
<link rel="stylesheet" type="text/css" href="css/ui.css">
</head>
<body>
<!-- 顶部 -->
<div class="top" id="top">
<div class="wrap">
<p class="call">3059482795qq预约</p>
<p class="welcome">欢迎来到CUMT医院预约挂号统一平台 请
<a href="#">登录</a>
<a href="#">注册</a>
<a href="#">帮助中心</a>
</p>
</div>
</div>
<!-- header区域 -->
<div class="header" id="header">
<div class="wrap">
<a class="logo" href="main.html"> <img src="" alt=""> </a>
<div class="search ui-search">
<!-- 搜索栏 -->
<div class="ui-search-selected">医院</div>
<div class="ui-search-select-list">
<a href="#1">科室</a>
<a href="#1">疾病</a>
<a href="#1">医院</a>
</div>
<input type="text" name="search-content" class="ui-search-input" placeholder="请输入搜索内容">
<a href="#" class="ui-search-submit"> </a>
</div>
</div>
</div>
<!-- 导航栏 -->
<div class="nav" id="nav">
<div class="wrap">
<div class="menu" ><a href="#" class="link">首页</a></div>
<a href="#" class="link">按医院挂号</a>
<a href="#" class="link">按科室挂号</a>
<a href="#" class="link">按疾病挂号</a>
<a href="#" class="link">最新公告</a>
<a href="#" class="link right">CUMT医院</a>
</div>
</div>
<!-- 医院简绍区域 -->
<div class="banner" id="banner">
<div class="wrap">
<div class="title">
<span class="title-left">CUMT附属子医院 <a href="#">关注医院</a></span>
<span class="title-right">
<span class="title-right-tips">等级:</span>三级甲等
<span class="title-right-tips">区域:</span>铜山区大学路一号
<span class="title-right-tips">分类:</span>中国医科院医院
</span>
</div>
<div class="banner-content">
<div class="left">
<img src="img/icon-call.png" alt="">
</div>
<div class="middle">
<span class="icon-address">铜山区大学路一号</span>
<span class="icon-web">http://www.cumt.edu.cn</span>
<span class="icon-tel">东院咨询台:010-69155564</span>
<span class="icon-trans">铜山区大学路一号</span>
</div>
<div class="right">
<img src="img/icon-call.png" alt="">
</div>
</div>
</div>
</div>
<!-- 医院体系区域 -->
<div class="content " id="content" >
<div class="wrap">
<!-- 导航栏 -->
<div class="nav">
<a href="#2" class="link selected">预约挂号</a>
<a href="#2" class="link">医院介绍</a>
<a href="#2" class="link">预约须知</a>
<a href="#2" class="link">停诊信息</a>
<a href="#2" class="link">查询取消</a>
</div>
<div class="schedule hidden" >
<span>科室排班表</span>
<span class="back"><a href="#">返回科室列表</a></span>
</div>
</div>
</div>
<div class="content-lists clearfix">
<div class="wrap clearfix">
<div class="content-list focus">
<div class="content-tab">
<div class="caption">开放预约科室</div>
<div class="content-table">
<table>
</table>
</div>
</div>
<div class="content-news">
<div class="caption">
预约规则
<span>更新时间每日8:30更新</span>
</div>
<div class="content-news-tips">
<div class="line">
<div class="line-name">预约周期:</div><div>7天</div>
</div>
<div class="line">
<div class="line-name">放号时间:</div><div>8:30</div>
</div>
<div class="line">
<div class="line-name">停诊时间:</div>
<div>下午14:00停止次日预约挂号,周五14:00停挂至下周一</div>
</div>
<div class="line">
<div class="line-name">退号时间:</div>
<div>就诊前一工作日14:00前取消</div>
</div>
<div class="line">
<div class="line-name">特殊规则:</div>
<div>取号地点不同:西院区预约号区号地点:
西院区门诊楼一层大厅挂号窗口取号。东院区预约号取号地点:东
院区老门诊楼一层大厅挂号窗口或新门诊楼各楼层挂号/收费窗口取号。</div>
</div>
</div>
</div>
</div>
<div class="content-list">
<!-- 医院介绍 -->
<div class="hospital-intro">
</div>
</div>
<div class="content-list">
<!-- 预约须知 -->
</div>
<div class="content-list">
<!-- 停诊信息 -->
<div class="stop-title">
停诊信息
</div>
<table class="stop-tips-table">
<tr>
<th>日期</th>
<th>星期</th>
<th>时段</th>
<th>科室</th>
<th>特长</th>
<th>职称</th>
<th>挂号费</th>
<th>可挂号数</th>
<th>剩余好数</th>
<th>替换方式</th>
</tr>
</table>
</div>
<div class="content-list">
<!-- 查询取消 -->
<div class="search-cancel">
<div class="line">
<span>预约识别码:</span>
<input type="text" name="" value="">
<button type="button" name="" value="">查询订单</button>
</div>
</div>
</div>
</div>
<div class="wrap clearfix hidden">
<table>
<tr>
<td>
<div class="leftBtn">
<div class="wrap_btn">
<div class="btn"></div>
</div>
<div class="status">上午</div>
<div class="status">下午</div>
<div class="status">晚上</div>
</div>
</td>
<td>
<div class="main">
<div class="schedule_box clearfix">
<!-- 模板
<div class="schedule_box_item">
<div class="date">星期一 <br>2019-01-01</div>
<div class="status"></div>
<div class="status status_full">约满</div>
<div class="status"></div>
</div>
-->
</div>
</div>
</td>
<td>
<div class="rightBtn">
<div class="wrap_btn">
<div class="btn"></div>
</div>
<div class="status"></div>
<div class="status"></div>
<div class="status"></div>
</div>
</td>
<td>
<div class="content-news">
<div class="title">
预约规则
</div>
<div class="line">
<div class="line-name">预约周期:</div><div>7天</div>
</div>
<div class="line">
<div class="line-name">放号时间:</div><div>8:30</div>
</div>
<div class="line">
<div class="line-name">停诊时间:</div>
<div>下午14:00停止次日预约挂号,周五14:00停挂至下周一</div>
</div>
<div class="line">
<div class="line-name">退号时间:</div>
<div>就诊前一工作日14:00前取消</div>
</div>
<div class="line">
<div class="line-name">特殊规则:</div>
<div>取号地点不同:西院区预约号区号地点:
西院区门诊楼一层大厅挂号窗口取号。东院区预约号取号地点:东
院区老门诊楼一层大厅挂号窗口或新门诊楼各楼层挂号/收费窗口取号。</div>
</div>
</div>
</td>
</tr>
<tr >
<td colspan="4">
<div class="bottom">
<span class="choice">您还没有选择就诊日期</span>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<!-- footer -->
<div class="footer" id="footer">
Copyright (c) 2021 Copyright Holder All Rights Reserved. by 许磊 信安18-1班作业
</div>
</body>
<!-- jquery的两种导入方式 -->
<!-- <script type="text/javascript" src="js/jquery-1.7.1.min.js"></script> -->
<script type="text/javascript" src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<!-- ui.js用到jquery库,所以jquery的库的导入要在ui.js之前,否则提示$未定义 -->
<script type="text/javascript" src="js/ui.js"></script>
</script>
</html>
ui.js
// ui-search 定义
$.fn.UiSearch = function(){
var ui = $(this);
$('.ui-search-selected',ui).on('click',function(){
$('.ui-search-select-list').show();
//return false是为了防止事件冒泡
return false;
});
$('.ui-search-select-list a',ui).on('click',function(){
$('.ui-search-selected').text( $(this).text() );
$('.ui-search-select-list').hide();
//return false是为了防止事件冒泡,防止触发下面body中点击事件
return false;
});
$('body').on('click',function(){
$('.ui-search-select-list').hide();
})
}
$.fn.UiCotentList= function(){
var ui = $(this);
var navs = $('.link',this);
var contentLists = $('.content-list');
$('.link',ui).on('click',function(){
var navIndex = $(this).index();
contentLists.removeClass('focus').eq(navIndex).addClass('focus');
navs.removeClass('selected').eq(navIndex).addClass('selected');
})
}
var j=0;
$.fn.slideSchedule = function(dir){
var ui = $(this);
// console.log(ui);
var width = $(".main").width();
var content = $(".schedule_box ");
$(this).click(function(){
if(dir=="left"){
j--;
if(j<0){
j=0;
return;
}
}else if(dir=="right"){
j++;
if(j>6){
j=6;
return;
}
}
var distance = -width*j;
console.log("j"+j);
console.log(distance+"px");
$(content).css("left",distance+"px");
})
}
$.fn.loadtable = function(){
var weeks = new Array('星期日','星期一','星期二','星期三','星期四','星期五','星期六');
for(var i=0;i<49;i++){
var currDate = new Date();
// getDay() 方法可返回一周(0~6)的某一天的数字。
// 星期天为 0, 星期一为 1, 以此类推。
currDate = new Date(currDate.getTime() + 24*60*60*1000*i);
var currWeekDay = currDate.getDay();
//获取当前日(1-31)
var currDay = currDate.getDate()
var currYear = currDate.getFullYear();
//getMonth(),一月份: 0
var currMonth = currDate.getMonth()+1;
var week = weeks[currWeekDay];
var str = week+'<br/>'+currYear+'-'+currMonth+'-'+currDay;
// console.log(str);
var html = new Array();
html.push('<div class="schedule_box_item"><div class="date">'+str+'</div>');
html.push('<div class="status"></div>');
html.push('<div class="status status_full">约满</div>');
html.push('<div class="status"></div></div>');
$('.schedule_box').append(html.join(''));
}
}
$.fn.back = function(){
$(this).on('click',function(){
$('.nav').removeClass('hidden');
$('.schedule').addClass('hidden');
$('.content-lists .wrap')[1].classList.add("hidden");
// var test = $('.content-lists .wrap')[0].classList;
// console.log(test);
$('.content-lists .wrap')[0].classList.remove("hidden");
})
}
$.fn.jump = function(){
$(this).on('click',function(){
console.log("click "+this);
$('.nav').addClass('hidden');
$('.schedule').removeClass('hidden');
$('.content-lists .wrap')[0].classList.add("hidden");
// var test = $('.content-lists .wrap')[0].classList;
// console.log(test);
$('.content-lists .wrap')[1].classList.remove("hidden");
})
}
//test 测试数据
$.fn.loadData = function(){
for(var i=0;i<4;i++){
//一共四科
for(var j=0;j<3;j++){
//一共3行
var eles = new Array();
eles.push('<tr>');
if(j==0){
eles.push('<td rowspan="3" class="classify">门诊</td>');
}
for(var k=0;k<4;k++){
eles.push('<td><a href="#" class="classify-item">口腔门诊</a></td>');
}
eles.push('</tr>')
// console.log(eles.join(''));
$(this).append(eles.join(''));
}
}
}
//test 测试数据
//页面初始化,事件绑定
$(document).ready(function(){
$('.ui-search').UiSearch();
$('.content .nav').UiCotentList();
$('.leftBtn .wrap_btn').slideSchedule("left");
$('.rightBtn .wrap_btn').slideSchedule("right");
$('.schedule_box').loadtable();
$('.back').back();
//test
$('.content-table table').loadData()
$('.classify-item').jump();
})
ui.css
// ui-search 定义
$.fn.UiSearch = function(){
var ui = $(this);
$('.ui-search-selected',ui).on('click',function(){
$('.ui-search-select-list').show();
//return false是为了防止事件冒泡
return false;
});
$('.ui-search-select-list a',ui).on('click',function(){
$('.ui-search-selected').text( $(this).text() );
$('.ui-search-select-list').hide();
//return false是为了防止事件冒泡,防止触发下面body中点击事件
return false;
});
$('body').on('click',function(){
$('.ui-search-select-list').hide();
})
}
$.fn.UiCotentList= function(){
var ui = $(this);
var navs = $('.link',this);
var contentLists = $('.content-list');
$('.link',ui).on('click',function(){
var navIndex = $(this).index();
contentLists.removeClass('focus').eq(navIndex).addClass('focus');
navs.removeClass('selected').eq(navIndex).addClass('selected');
})
}
var j=0;
$.fn.slideSchedule = function(dir){
var ui = $(this);
// console.log(ui);
var width = $(".main").width();
var content = $(".schedule_box ");
$(this).click(function(){
if(dir=="left"){
j--;
if(j<0){
j=0;
return;
}
}else if(dir=="right"){
j++;
if(j>6){
j=6;
return;
}
}
var distance = -width*j;
console.log("j"+j);
console.log(distance+"px");
$(content).css("left",distance+"px");
})
}
$.fn.loadtable = function(){
var weeks = new Array('星期日','星期一','星期二','星期三','星期四','星期五','星期六');
for(var i=0;i<49;i++){
var currDate = new Date();
// getDay() 方法可返回一周(0~6)的某一天的数字。
// 星期天为 0, 星期一为 1, 以此类推。
currDate = new Date(currDate.getTime() + 24*60*60*1000*i);
var currWeekDay = currDate.getDay();
//获取当前日(1-31)
var currDay = currDate.getDate()
var currYear = currDate.getFullYear();
//getMonth(),一月份: 0
var currMonth = currDate.getMonth()+1;
var week = weeks[currWeekDay];
var str = week+'<br/>'+currYear+'-'+currMonth+'-'+currDay;
// console.log(str);
var html = new Array();
html.push('<div class="schedule_box_item"><div class="date">'+str+'</div>');
html.push('<div class="status"></div>');
html.push('<div class="status status_full">约满</div>');
html.push('<div class="status"></div></div>');
$('.schedule_box').append(html.join(''));
}
}
$.fn.back = function(){
$(this).on('click',function(){
$('.nav').removeClass('hidden');
$('.schedule').addClass('hidden');
$('.content-lists .wrap')[1].classList.add("hidden");
// var test = $('.content-lists .wrap')[0].classList;
// console.log(test);
$('.content-lists .wrap')[0].classList.remove("hidden");
})
}
$.fn.jump = function(){
$(this).on('click',function(){
console.log("click "+this);
$('.nav').addClass('hidden');
$('.schedule').removeClass('hidden');
$('.content-lists .wrap')[0].classList.add("hidden");
// var test = $('.content-lists .wrap')[0].classList;
// console.log(test);
$('.content-lists .wrap')[1].classList.remove("hidden");
})
}
//test 测试数据
$.fn.loadData = function(){
for(var i=0;i<4;i++){
//一共四科
for(var j=0;j<3;j++){
//一共3行
var eles = new Array();
eles.push('<tr>');
if(j==0){
eles.push('<td rowspan="3" class="classify">门诊</td>');
}
for(var k=0;k<4;k++){
eles.push('<td><a href="#" class="classify-item">口腔门诊</a></td>');
}
eles.push('</tr>')
// console.log(eles.join(''));
$(this).append(eles.join(''));
}
}
}
//test 测试数据
//页面初始化,事件绑定
$(document).ready(function(){
$('.ui-search').UiSearch();
$('.content .nav').UiCotentList();
$('.leftBtn .wrap_btn').slideSchedule("left");
$('.rightBtn .wrap_btn').slideSchedule("right");
$('.schedule_box').loadtable();
$('.back').back();
//test
$('.content-table table').loadData();
$('.classify-item').jump();
})
layout.css
body{
margin: 0;
padding: 0;
}
.clearfix:after{
content: ' ';
display: block;
height: 0;
line-height: 0;
clear: both;
zoom: 1;
}
.wrap{
width: 1000px;
margin:0 auto;
position: relative;
/* background-color: pink; */
}
/* 顶部 */
.top {
height: 30px;
background-color: #f5f5f5;
}
.header{
height: 92px;
}
/* 导航栏 */
.nav{
height: 36px;
background-color: #60bff2;
}
/* 医院简绍区域 */
.banner{
width: 1000px;
margin: 30px auto;
height: 310px;
/* background-color: #F7F7F7; */
}
/* 医院体系区域 */
.content{
padding: 10px 0 10px 0;
font-size: 14px;
/* min-height: 520px; */
}
.content-lists .wrap{
height: auto;
}
.content-list{
width: 100%;
font-size: 14px;
}
.content-tab{
float: left;
width: 720px;
height: 410px;
margin-right: 20px;
border: 1px solid #ccc;
}
.content-news{
float: right;
width: 248px;
height: 270px;
border: 1px solid #ccc;
}
.footer{
height: 70px;
padding: 25px 0;
background-color: #eceef2;
margin-top: 20px;
}
base.css
p{
margin: 0;
padding: 0;
display: inline-block;
}
a{
text-decoration: none;
}
select,input{
border: none;
outline: none;
}
/* #top 模块内样式 */
.top{
line-height: 30px;
font-size: 13px;
color: #868686;
}
.top .call{
float: left;
padding-left: 20px;
background: url(../img/icon-call.png) no-repeat center left;
}
.top .welcome{
float: right;
}
.top a{
color: #2da5e1;
padding-left: 10px;
}
/* #header 模块内样式 */
.header .logo{
width: 402px;
height: 74px;
padding: 9px 0;
display: inline-block;
background-color: pink;
}
.header .logo img{
width: 100%;
height: 100%;
}
.header .search {
width: 326px;
height: 38px;
position: absolute;
right: 0px;
top: 29px;
background-color: orange;
}
/* 导航栏 */
/* #nav 模块内样式 */
.nav .link{
display: inline-block;
float: left;
padding-left: 30px;
line-height: 36px;
color: #fff;
font-size: 16px;
min-width: 80px;
text-align: center;
}
.nav .right{
float: right;
}
.nav a:hover{
color: #d7f3ff;
}
/* 医院简绍区域 */
/* 医院简绍区域 */
.banner .wrap{
background-color: #F7F7F7;
height: 280px;
/* padding: 20px 20px; */
}
.banner .title{
height: 30px;
border-bottom: 1px solid #acacac;
margin: 10px 20px;
padding-top:10px;
}
.banner .title .title-left{
float: left;
}
.banner .title .title-left a{
color: orange;
font-size: 12px;
}
.banner .title .title-right{
float: right;
font-size: 12px;
}
.banner .title .title-right .title-right-tips{
color: blue;
}
.banner .banner-content{
margin: 10px 20px;
}
.banner .banner-content .left{
float: left;
width: 200px;
height: 150px;
background-color: pink;
}
.banner .banner-content .middle{
float: left;
width:450px;
font-size: 12px;
color:#acacac;
margin-left: 20px;
margin-right: 20px;
}
.banner .banner-content .middle span{
padding-left: 20px;
display: inline-block;
width: 100%;
height: 20px;
line-height: 20px;
background: url(../img/icon-web.png) 0px 0px no-repeat;
}
.banner .banner-content .middle .icon-address{
background: url(../img/icon-web.png) 0px 0px no-repeat;
}
.banner .banner-content .middle .icon-web{
background-position: 0 -20px;
}
.banner .banner-content .middle .icon-tel{
background-position: 0 -40px;
}
.banner .banner-content .middle .icon-trans{
background-position: 0 -60px;
}
.banner .banner-content .right{
float: right;
width: 250px;
height: 212px;
background-color: pink;
}
/* 医院体系区域 */
/* 医院体系区域 导航栏*/
.content .nav{
width: 100%;
height: 36px;
background-color:white;
border-bottom: 2px solid #60bff2;
margin-bottom: 10px;
}
.content .nav .link{
color:#60bff2;
padding-left: 0px;
margin-right: 30px;
min-width: 100px;
}
.content .nav .selected{
background-color: #60bff2;
color: #fff;
}
.content .schedule{
width: 100%;
height: 36px;
margin-bottom: 12px;
font-size: 16px;
font-weight: bold;
}
/* .content .schedule .back{
margin-left: 10px;
font-size: 14px;
font-weight: normal;
color:#60bff2;
} */
.content .schedule .back a{
margin-left: 10px;
font-size: 14px;
font-weight: normal;
color:#60bff2;
}
/* 预约挂号 */
.content-lists .content-news .caption,
.content-lists .content-tab .caption{
background-color: #eceef2;
height: 36px;
line-height: 36px;
padding-left: 20px;
}
.content-lists .content-news .caption{
color:#acacac;
padding-left: 8px;
}
.content-lists .content-news .caption span{
color:#60bff2;
font-size: 12px;
}
/* .content .content-tab .content-table table, th, td */
.content-lists .content-list{
display: none;
}
.content-lists .focus{
display: block;
}
.content-table table,
.content-table tr,
.content-table td{
border: 0px;
border-collapse:collapse;
}
.content-table td{
width:120px;
height: 30px;
line-height: 30px;
}
.content-table td a{
font-weight: bold;
padding-left: 20px;
color: black;
}
.content-tab .content-table .classify{
width:200px;
background-color: #CEFFCE;
vertical-align:top;
text-align: center;
}
.content-tab .content-table .classify-item{
width:120px;
}
.content-lists .content-news .content-news-tips{
height: 236px;
overflow: auto;
}
.content-lists .content-news .line{
color:#acacac;
line-height: 20px;
font-size: 12px;
width: 100%;
}
.content-lists .content-news .line div{
display: inline-block;
float: left;
padding-top: 5px;
width: 130px;
}
.content-lists .content-news .line .line-name{
color:black;
width: 60px;
padding-left: 8px;
}
/* 医院介绍 */
/* 预约须知 */
/* 停诊信息 */
.content-list .stop-title{
text-align: center;
height: 38px;
line-height: 38px;
font-weight: bold;
font-size: 16px;
}
.content-list .stop-tips-table th,
.content-list .stop-tips-table td,
.content-list .stop-tips-table{
font-size: 12px;
font-weight: normal;
color:#acacac;
border: 1px solid #acacac;
padding: 5px 10px;
text-align: center;
border-collapse:collapse;
}
.content-list .stop-tips-table{
margin: 0 auto;
}
.content-list .stop-tips-table th{
min-width: 50px;
}
.content-list .stop-tips-table th:nth-of-type(4){
width: 200px;
}
.content-list .stop-tips-table th:nth-of-type(6){
width: 120px;
}
/* 查询取消 */
.search-cancel{
padding: 100px;
border:1px solid #acacac;
}
.search-cancel .line{
margin: 0 auto;
width: 400px;
height: 40px;
line-height: 40px;
/* background-color: yellow; */
text-align: center;
}
.search-cancel .line input{
width: 200px;
border:1px solid #acacac;
height: 18px;
/* display: inline-block; */
vertical-align: middle;
margin-left: 10px;
}
.search-cancel .line button{
width: 80px;
height: 20px;
background-color: #60bff2;
border-width: 0px;
color:white;
font-size: 12px;
/* margin-top: 5px; */
vertical-align: middle;
margin-left: 10px;
}
.search-cancel .line button:hover{
cursor: pointer;
}
/* 科室排班表 */
.content-lists .wrap:nth-of-type(2) table{
width: 1000px;
height: 320px;
border-collapse:collapse;
border: 1px solid #ccc;
}
.content-lists .wrap:nth-of-type(2) table td{
border: 1px solid #ccc;
}
.content-lists .wrap .rightBtn,
.content-lists .wrap .leftBtn{
width: 25px;
/* float: left; */
height: 270px;
/* border-right: 1px solid #ccc; */
}
.content-lists .wrap .wrap_btn{
height: 30px;
}
.content-lists .wrap .rightBtn .status,
.content-lists .wrap .leftBtn .status{
height: 80px;
line-height: 40px;
text-align: right;
padding-right: 2px;
background-color: #CEFFCE;
font-size: 12px;
}
.content-lists .wrap .leftBtn .btn{
width: 0;
height: 0;
border-width: 10px;
border-style: solid;
border-color: transparent #60bff2 transparent transparent;
margin-right: 7px;
}
.content-lists .wrap .rightBtn .btn{
width: 0;
height: 0;
border-width: 10px;
border-style: solid;
border-color: transparent transparent transparent #60bff2;
margin-left: 7px;
}
.content-lists .wrap .main{
/* width : 90px * 7 */
width: 700px;
float: left;
height: 270px;
overflow: hidden;
position: relative;
margin: 0 auto;
}
.content-lists .wrap:nth-of-type(2) .content-news{
/* 1000 - 25 *2 - 700 = 250px; */
/* width: 248px; */
height: 270px;
/* position: absolute;
top:0px;
right: 0px; */
overflow: auto;
/* float: right; */
border: 0px;
}
.content-lists .wrap .content-news .title{
font-size: 16px;
text-align: center;
font-weight: bold;
height: 30px;
line-height: 30px;
}
.content-lists .wrap .bottom{
width: 1000px;
height: 50px;
/* border-top: 1px solid #acacac; */
line-height: 50px;
text-align: center;
}
.content-lists .wrap .bottom .choice{
background: url(../img/icon-web.png) 0 0 no-repeat;
padding-left: 30px;
}
/* footer */
.footer{
line-height: 70px;
text-align: center;
font-size: 12px;
color: #666;
}
第二部分:设计实现虚拟专用网(能力有限、水平一般、部分参考网上资源)
一、工作流程
模拟一个网页请求流程
1、Firefox在笔记本发出一个请求。
2、内核使用默认路由发送这个请求的IP包。
3、因为默认路由的设备设置的是tun0,所以被tunnel程序捕获。
4、tunnel程序读取ip包后,用icmp封装,发送到远程vps。
5、icmp无障碍地通过cmwap网络,发送到远程vps上。
6、远程vps收到后,被服务器端的tunnel程序捕获(tunnel程序捕获所有的icmp数据包)。
7、tunnel程序读取icmp包,获取里面的ip包,写入到本地网络中。
8、因为通过iptables设置了nat,所以该ip包的源地址被改为vps ip后,发送到了所请求的服务器上。
9、一个IP包从请求的服务器上返回到vps,经过nat后,进入tunnel程序建立的网络,被tunnel程序捕获。
10、tunnel程序读取ip包后,用icmp封装,发送到笔记本。
11、icmp回应包无障碍地通过cmwap网络,发送到笔记本上。
12、笔记本接收到该icmp包,被笔记本上的tunnel程序捕获。
13、tunnel程序读取icmp包,获取里面的ip包,写入到本地网络中。
14、内核得到这个ip包,通知指定的应用程序响应。
15、Firefox收到了回应。
关键需要解决的是封装ip包和解除封装
二、要解决的问题
2.1如何捕获与发送icmp包
socket的RAW模式即原始套接字
2.2如何不影响vps上正常的ping回应
给icmp里的code字段设置一个固定值,默认是0,这个值可以随便设置。例如86。这样我们只捕获与发送code值为86的icmp数据包。跟普通的ping区别开来,互不影响。
同时,避免vps的内核回应我们的icmp包。添加下面的iptables规则。使用到--icmp-type type/code选项。type的值中,8是ping请求,0是ping响应,所以只针对响应包屏蔽。但是为了让服务器端的tunnel程序的icmp能发出去,服务器端在发送的时候,可以把code+1,也就变为87,发送出去。
2.3 MTU问题
因为IP包被封装到ICMP里之后,体积肯定会变大,如果超出网络的MTU,内核就会用两个IP包来装。导致第一个IP包装满了,第二个IP包可能只有几十个字节。十分浪费。为了避免这种现象,可以设置虚拟网卡的mtu为1000或更少
2.4 Python处理ICMP
Python 的 stdlib 没有任何用于支持 ICMP 数据包的包含库,,但ICMP数据包是常见和有用的:它们既用于跟踪路线,也用于平公用设施。因此,它们可用于控制网络诊断。
数据包类是用于创建和读取ICMP数据包的内容。要创建一个数据包,请将类瞬间化,设置头和数据字段,然后调用创建()方法,该方法将字符串表示可以传递到插座。
要读取数据包,请使用"parse()类模组",该分类将返回已填写字段的包实例。
为了显示其使用,您还可以看到包含的 ping()方法。只需将代码用作脚本,并将地址传递给ping。
三、运行虚拟专用网
Kali运行虚拟专用网
ip route show
乌班图运行虚拟专用网
成功
到目前为止,已经在两台机器之间通过icmp建立了点对点隧道
构建虚拟专用网
先在kali服务器端设置NAT
iptables -t nat -A POSTROUTING -s 10.1.2.0/24 -j SNAT --to-source 192.168.111.130
再在本地设置路由表,让默认网关为新创建的t0
成功建立虚拟专用网
四、实现的功能
1)支持多人同时使用这个。每个客户端通过外网IP与ICMP里的ID的组合来决定。所以,即使多个使用者在同一个局域网下,也不会相互使用。参见代码中key的计算。
2)使用密码登录以限制他人访问。初次连接服务器要求密码才能使用该。默认为10分钟收不到来自客户端的数据包就删除会话。
3)服务器端和客户端共用一个tunnel程序。通过参数来指定工作模式。
附录
tunnel.py
#!/usr/bin/env python
import os, sys
import hashlib
import getopt
import fcntl
import icmp
import time
import struct
import socket, select
SHARED_PASSWORD = hashlib.md5("password").digest()
TUNSETIFF = 0x400454ca
IFF_TUN = 0x0001
MODE = 0
DEBUG = 0
PORT = 0
IFACE_IP = "10.0.0.1"
MTU = 1500
CODE = 86
TIMEOUT = 60*10 # seconds
class Tunnel():
def create(self):
self.tfd = os.open("/dev/net/tun", os.O_RDWR)
ifs = fcntl.ioctl(self.tfd, TUNSETIFF, struct.pack("16sH", "t%d", IFF_TUN))
self.tname = ifs[:16].strip("\x00")
def close(self):
os.close(self.tfd)
def config(self, ip):
os.system("ip link set %s up" % (self.tname))
os.system("ip link set %s mtu 1000" % (self.tname))
os.system("ip addr add %s dev %s" % (ip, self.tname))
def run(self):
self.icmpfd = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
self.clients = {}
packet = icmp.ICMPPacket()
self.client_seqno = 1
while True:
rset = select.select([self.icmpfd, self.tfd], [], [])[0]
for r in rset:
if r == self.tfd:
if DEBUG: os.write(1, ">")
data = os.read(self.tfd, MTU)
if MODE == 1: # Server
for key in self.clients:
buf = packet.create(0, CODE+1, self.clients[key]["id"], self.clients[key]["seqno"], data)
self.clients[key]["seqno"] += 1
self.icmpfd.sendto(buf, (self.clients[key]["ip"], 22))
# Remove timeout clients
curTime = time.time()
for key in self.clients.keys():
if curTime - self.clients[key]["aliveTime"] > TIMEOUT:
print "Remove timeout client", self.clients[key]["ip"]
del self.clients[key]
else: # Client
buf = packet.create(8, CODE, PORT, self.client_seqno, data)
self.client_seqno += 1
self.icmpfd.sendto(buf, (IP, 22))
elif r == self.icmpfd:
if DEBUG: os.write(1, "<")
buf = self.icmpfd.recv(icmp.BUFFER_SIZE)
data = packet.parse(buf, DEBUG)
ip = socket.inet_ntoa(packet.src)
if packet.code in (CODE, CODE+1):
if MODE == 1: # Server
key = struct.pack("4sH", packet.src, packet.id)
if key not in self.clients:
# New client comes
if data == SHARED_PASSWORD:
self.clients[key] = {"aliveTime": time.time(),
"ip": ip,
"id": packet.id,
"seqno": packet.seqno}
print "New Client from %s:%d" % (ip, packet.id)
else:
print "Wrong password from %s:%d" % (ip, packet.id)
buf = packet.create(0, CODE+1, packet.id, packet.seqno, "PASSWORD"*10)
self.icmpfd.sendto(buf, (ip, 22))
else:
# Simply write the packet to local or forward them to other clients ???
os.write(self.tfd, data)
self.clients[key]["aliveTime"] = time.time()
else: # Client
if data.startswith("PASSWORD"):
# Do login
buf = packet.create(8, CODE, packet.id, self.client_seqno, SHARED_PASSWORD)
self.client_seqno += 1
self.icmpfd.sendto(buf, (ip, 22))
else:
os.write(self.tfd, data)
def usage(status = 0):
print "Usage: icmptun [-s code|-c serverip,code,id] [-hd] [-l localip]"
sys.exit(status)
if __name__=="__main__":
opts = getopt.getopt(sys.argv[1:],"s:c:l:hd")
for opt,optarg in opts[0]:
if opt == "-h":
usage()
elif opt == "-d":
DEBUG += 1
elif opt == "-s":
MODE = 1
CODE = int(optarg)
elif opt == "-c":
MODE = 2
IP,CODE,PORT = optarg.split(",")
CODE = int(CODE)
PORT = int(PORT)
elif opt == "-l":
IFACE_IP = optarg
if MODE == 0 or CODE == 0:
usage(1)
tun = Tunnel()
tun.create()
print "Allocated interface %s" % (tun.tname)
tun.config(IFACE_IP)
try:
tun.run()
except KeyboardInterrupt:
tun.close()
sys.exit(0)
icmp.py
#!/usr/bin/env python
import socket
import binascii
import struct
import ctypes
BUFFER_SIZE = 8192
class IPPacket():
def _checksum(self, data):
if len(data) % 2:
odd_byte = ord(data[-1])
data = data[:-1]
else:
odd_byte = 0
words = struct.unpack("!%sH" %(len(data)/2), data)
total = 0
for word in words:
total += word
else:
total += odd_byte
total = (total>>16) + (total & 0xffff)
total += total>>16
return ctypes.c_ushort(~total).value
def parse(self, buf, debug = True):
self.ttl, self.proto, self.chksum = struct.unpack("!BBH", buf[8:12])
self.src, self.dst = buf[12:16], buf[16:20]
if debug:
print "parse IP ttl=", self.ttl, "proto=", self.proto, "src=", socket.inet_ntoa(self.src), \
"dst=", socket.inet_ntoa(self.dst)
class ICMPPacket(IPPacket):
def parse(self, buf, debug = True):
IPPacket.parse(self, buf, debug)
self.type, self.code, self.chksum, self.id, self.seqno = struct.unpack("!BBHHH", buf[20:28])
if debug:
print "parse ICMP type=", self.type, "code=", self.code, "id=", self.id, "seqno=", self.seqno
return buf[28:]
def create(self, type_, code, id_, seqno, data):
packfmt = "!BBHHH%ss" % (len(data))
args = [type_, code, 0, id_, seqno, data]
args[2] = IPPacket._checksum(self, struct.pack(packfmt, *args))
return struct.pack(packfmt, *args)
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
