范围
适用于中国电信使用的Apache服务器。本规范提出了Apache服务器安全配置要求,
适用于所有的安全等级,可作为编制设备入网测试、安全验收、安全检查规范等文档的参考。
由于版本不同,配置操作有所不同,本规范以 unix 平台上 Apache2.02.2 为例,
给出参考配置操作。
缩略语
安全配置要求
账号
授权
编号:1
编号:2
适用于中国电信使用的Apache服务器。本规范提出了Apache服务器安全配置要求,
适用于所有的安全等级,可作为编制设备入网测试、安全验收、安全检查规范等文档的参考。
由于版本不同,配置操作有所不同,本规范以 unix 平台上 Apache2.02.2 为例,
给出参考配置操作。
编号:1
编号:2
Apache httpd服务器在缺省的情况下,开启了基于目录列表的访问,这是一个存在安全隐患的问题,因此可以关闭这个功能。在Apache 2.4的版本中,不在支持使用-indexes来配置,需要注释该功能。本文对此给出演示,供大家参考。
当前环境
[root@centos7-web ~]# more /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[root@centos7-web ~]# apachectl -v
Server version: Apache/2.4.6 (CentOS)
Server built: Nov 19 2015 21:43:13
为站点添加index.html页面
# echo "This is a apache test index page" > /var/www/html/index.html
[root@centos7-web ~]# curl http://localhost
This is a apache test index page
移除index.html
[root@centos7-web ~]# mv /var/www/html/index.html /var/www/html/index.tmp
依旧可以访问,不过此时为apache的缺省欢迎页面
移除apache欢迎页面
[root@centos7-web ~]# mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.bk
[root@centos7-web ~]# cp /usr/share/backgrounds/* /var/www/html/.
[root@centos7-web ~]# grep -Ev "^$|^#|*#" /etc/httpd/conf/httpd.conf >/etc/httpd/conf/httpd.conf.tmp
[root@centos7-web ~]# cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.1106
[root@centos7-web ~]# mv /etc/httpd/conf/httpd.conf.tmp /etc/httpd/conf/httpd.conf
mv: overwrite ‘/etc/httpd/conf/httpd.conf’? yes
[root@centos7-web ~]# vim /etc/httpd/conf/httpd.conf
[root@centos7-web ~]# grep "Indexes" -B1 -A3 /etc/httpd/conf/httpd.conf 查看修改后的结果
<Directory "/var/www/html">
# Options Indexes FollowSymLinks ##注释该行
AllowOverride None
Require all granted
</Directory>
[root@centos7-web ~]# systemctl reload httpd
[root@centos7-web ~]# curl http://localhost
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /
on this server.</p>
</body></html>
[root@centos7-web ~]# ln -sv /etc/redhat-release /var/www/html/redhat-release.html
‘/var/www/html/redhat-release.html’ -> ‘/etc/redhat-release’
[root@centos7-web ~]# ls -hltr /var/www/html/redhat-release.html
lrwxrwxrwx 1 root root 19 Sep 21 16:15 /var/www/html/redhat-release.html -> /etc/redhat-release
[root@centos7-web ~]# curl http://localhost/redhat-release.html
CentOS Linux release 7.2.1511 (Core)
[root@centos7-web ~]# vim /etc/httpd/conf/httpd.conf
Options None ##改成Options None
[root@centos7-web ~]# systemctl reload httpd
[root@centos7-web ~]# curl http://localhost/redhat-release.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body> ##Author : Leshami
<h1>Forbidden</h1> ## Blog : http://blog.csdn.net/leshami
<p>You don't have permission to access /redhat-release.html
on this server.</p>
</body></html>
provider
VMware
AWS
安装、启动、进入虚拟机就参见这个链接吧。注意:
be careful about rm -rf /, since Vagrant shares a directory at /vagrant with the directory on the host containing your Vagrantfile
vagrant init <box-name-on-cloud> # 生成 Vagrantfile 文件
vagrant up [--provider=virtualbox|vmware_fusion|aws] # 下载、配置、启动虚拟机
vagrant ssh # 连接虚拟机
vagrant destroy
vagrant reload [--provision] # 重新载入配置
vagrant share # 通过 ngrok 内网穿透功能实现让全世界人可以访问虚拟机的服务
vagrant status # 查看虚拟机状态
搜索可用虚拟机镜像(box):Discover Vagrant Boxes – Vagrant Cloud
其他镜像:http://www.vagrantbox.es/
vagrant suspend # 休眠
vagrant halt # 关机
vagrant destroy # 关机并完全销毁所有相关资源
vagrant package # 打包生成 package.box 文件
vagrant box add <vm-name> <box-file-path> # 添加box
配置都保存在 Vagrantfile 这个文件里。
(待续)
VBoxManage path on OSX
/Applications/VirtualBox.app/Contents/MacOS/VBoxManage
Fix it by soft link
ln -s /Applications/VirtualBox.app/Contents/MacOS/VBoxManage /usr/local/bin/VBoxMange
vagrant up无反应 on Win7
因为windows上vagrant和virtualbox版本不兼容,参见在windows 7中vagrant up 无反应,没任何信息输出 成功解决,但是出现 0x80004005 错误。
E_FAIL (0x80004005) on Win7
返回 代码: E_FAIL (0x80004005)
组件: Machine
界面: IMachine {480cf695-2d8d-4256-9c7c-cce4184fa048}
Try to solve but failed, possible solutions:
本文介绍了vagrant和安装,配置,启动和打包。还有,垃圾windows!
这两天用vagrant+virtualbox搭建环境,按照以前的方法,先把它们都下载下来都是最新版本。接着傻瓜式的安装,添加box、初始化,接着vagrant up启动。然而并没有启动起来,光标一直在那里闪烁。瞬间意识到踩坑了。经过百度,Google,都说是版本问题,果断换版本。
这时候的用的版本VirtualBox-5.1.18-114002-Win.exe、vagrant_1.9.3.msi。完事之后vagrant up,结果命令错误,一个很奇怪的问题,提示没有配置系统变量,但是我已经配置了,还是提示一样的错误。
具体提示
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
"rsync" could not be found on your PATH. Make sure that rsync
is properly installed on your system and available on the PATH.
解决方法:
打开目录,C:UsersAdministrator.vagrant.dboxescentos7.0virtualboxVagrantfile
Vagrant.configure("2") do |config|
config.vm.base_mac = "525400cae48b"
config.vm.synced_folder ".", "/vagrant", type: "rsync"
end
改成
Vagrant.configure("2") do |config|
config.vm.base_mac = "525400cae48b"
config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
end
yum install libjpeg-turbo-devel libjpeg-turbo libpng-devel -y
cd /usr/local/src
wget http://download.osgeo.org/libtiff/tiff-4.0.8.tar.gz
tar -zxvf tiff-4.0.8.tar.gz
cd tiff-4.0.8
./configure
make
make install
cd /usr/local/src
wget https://downloads.sourceforge.net/giflib/giflib-5.1.4.tar.bz2
tar -jxvf giflib-5.1.4.tar.bz2
cd giflib-5.1.4
./configure
make
make install
cd /usr/local/src
wget http://downloads.webmproject.org/releases/webp/libwebp-0.6.0.tar.gz
tar -zxvf libwebp-0.6.0.tar.gz
cd libwebp-0.6.0
./configure --enable-libwebpmux
--enable-libwebpdemux
--enable-libwebpdecoder
--enable-libwebpextras
--enable-swap-16bit-csp
--disable-static
make
make install
cwebp -q 75 IIS.png -o IIS-2.webp
cwebp -q 80 image.png -o image.webp
dwebp image.webp -o image.png
[root@tracker waf]# vim /usr/local/nginx/conf/lua/webp.lua
--检测路径是否目录,新增
local function is_dir(sPath)
if type(sPath) ~= "string" then
return false
end
local response = os.execute("cd " .. sPath)
if response == 0 then
return true
end
return false
end
-- 检测文件是否存在
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
--获取文件路径,新增
function getFileDir(filename)
return string.match(filename, "(.+)/[^/]*%.%w+$")
end
-- 检测图片路径,新增
--if not is_dir(getFileDir(ngx.var.img_thumb_path)) then
-- os.execute("mkdir -p " .. getFileDir(ngx.var.img_thumb_path))
-- end
if not is_dir(getFileDir(ngx.var.filename)) then
os.execute("mkdir -p " .. getFileDir(ngx.var.filename))
end
local newFile = ngx.var.request_filename;
local originalFile = newFile:sub(1, #newFile - 5); -- 去掉 .webp 的后缀
if not file_exists(originalFile) then -- 原文件不存在
ngx.exit(404);
return;
end
--local command = [[/usr/local/GraphicsMagick/bin/gm convert -quality 75 -density 72 +profile "*" ]] .. ngx.var.request_filepath .. originalUri .. " -geometry " .. " " .. ngx.var.request_filename;
os.execute("/usr/local/bin/cwebp -q 75 " .. originalFile .. " -o " .. newFile); -- 转换原图片到 webp 格式,这里的质量是 75 ,你也可以改成别的
if file_exists(newFile) then -- 如果新文件存在(转换成功)
ngx.exec(ngx.var.uri) -- Internal Redirect
else
ngx.exit(404)
end
server {
listen 8216;
#charset utf-8;
server_name 10.160.43.105;
index index.php index.html;
root /data/wwwroot/v2.50/wap.static/dist_dev;
#if (!-e $request_filename) {
# rewrite .* /index.php last;
#}
# goole ngx_pagespeed
# include extra/pagespeed.conf;
#PHP support
location ~ .*.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
location ~* ^(.+.(jpg|jpeg|gif|png)).webp$ {
set $webp_root /data/wwwroot/v2.50/wap.static/dist_dev;
root $webp_root;
#if (!-f $request_filename) {
set $filename $webp_root$uri;
if (!-f $filename) {
set $request_filepath $webp_root$1;
content_by_lua_file "/usr/local/nginx/conf/lua/webp.lua";
}
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 测试lua安装是否成功
# location /hello {
# default_type 'text/plain';
# content_by_lua 'ngx.say("hello, lua")';
#}
#log file
access_log logs/m250_access.log access;
}
如果需要在 Lua 中处理错误,必须使用函数 pcall(protected call)来包装需要执行的代码。 pcall 接收一个函数和要传递给后者的参数,并执行,执行结果:有错误、无错误;返回值 true 或者或 false, errorinfo。
pcall本质上是使用“保护模式”来运行第一参数,因此可以捕获运行过程中的错误。
给一个Cjson的例子:
local json = require("cjson")
local str = [[ {"key:"value"} ]]
local t = json.decode(str)
ngx.say(" --> ", type(t))
可以看到,需要解析的str是不完整的,缺少一个”,如果运行,将直接返回500内部错误。这显然不是我们想看到的。为了捕获这个问题,我们将decode封装一层,然后使用pcall来调用。
local json = require("cjson")
local str = [[ {"key:"value"} ]]
function _json_decode(str)
return json.decode(str)
end
function json_decode(str)
local ok, t = pcall(_json_decode, str)
if not ok then
return nil
else
return t
end
end
local t = json_decode(str)
ngx.say(" --> ", type(t))
我们将json.decode封装起来,并使用pcall函数来调用,同样传入错误的字符串,函数会判断实行有异常,然后返回nil。这样我们就有了处理异常的机制。
索引如果没有特指,一般是指B+TREE,通常意味着所有值都是顺序存放,因此对于范围查询会非常快。InnoDB按照原数据格式进行存储。InnoDB存储引擎表是索引组织表,表中数据按照主键存放(InnoDB会隐式定义一个主键作为聚集索引,切记不能重复定义)。索引的叶节点中存放表的行记录,使叶节点成为数据页。而普通索引仅仅存放键值以及偏移量而已。(ps:MYISAM使用前缀压缩使索引更小,表中数据是通过索引所记录的数据物理的位置,直接引用的。)
Tips1:
范围查询非常快
eg:limit 优化
select * from yanxue8_visit limit 10,10
多次运行,时间保持在0.0004-0.0005之间
Select * From yanxue8_visit Where vid >=(
Select vid From yanxue8_visit Order By vid limit 10,1
) limit 10
Tips2:
在使用索引时需要独立的列
eg:
select * from tablename where id +1 = 5
这样的写法是不能用索引的,这也是为什么很多mysql优化语句中常提到的一点。
Tip3:
可以使用前缀索引
eg:
alter table tablename add key(a(7))
这样可以使索引变小并变快,节约空间,提高索引效率。但会减小索引的选择性。
前缀索引,一种优化索引大小的解决方案: https://yq.aliyun.com/articles/39841
事实上,聚集索引页有些缺点,提高了使用磁盘I/O的次数。并且要严格按照插入顺序插入,否则可能面临数据页分裂,耗用更多空间并降低性能。因此我们都需要一个自增长键作为主键,保证数据顺序写入。若使用UUID情况会变糟糕,所以现在分布式系统基本放弃了原生的UUID寻找替代品。
辅助索引只是存取了聚集索引的书签。若想查询需要对辅助索引遍历一遍再在聚集索引遍历一遍,遍历深度由索引树高度决定。
联合索引顾名思义是多索引组成的联合索引.
如一张t表中有两列,a与b,其中a为主键,b为普通列
创建:alter table t add key idx_a_b(a,b)
如上图,数据先根据a排放,a值相同则根据b排放。既该索引包括了a与b的笛卡尔积。若where a = xxx and b = xxx 以及 where a = xxx则可以利用该索引,但where b = xxx 就不能利用该索引。(最左前缀)
好处:
可以联合读取多个列
可以做联合排序
Tip1:
利用多列条件做分页操作
创建:alter table tablename add key idx_a_b(a,b)
select * from tablename t1
left join(
select id from tablename
where a = 1 oder by b limit 1000,10) t2
on t1.id = t2.id
但事实上,也不能一棒子拍死。查询结果会非常依赖于选定的具体指,会对其他查询不公平,会使服务器运行不如预期。其顺序必须以选择性高低进行排序。事实上实际开发中,本人是因为某个查询量大的业务才建立联合索引,基本业务也是单个索引(但要注意重复索引,如我创建了(a,b)就得把(a)索引删除)。
InnoDB中只用哈希对字典进行查找,事实上,哈希表只需理解有这么个东西就行。InnoDB会自动创建哈希表并维护,并只是对字典查询会变快(where a = ‘xxx’),不对范围查询起作用。
innodb_adaptive_hash_index 启用/禁用特性
innodb_buffer_pool_size/256=哈希的槽数
explain
非常强大的工具,分析sql语句的性能以及所运用的索引。可以解决绝大多数sql性能问题。
慢查询日志
超过阈值的SQL语句记录的日志。
show index from tablename
可以分析表中索引,有些字段对于分析该表索引非常有用,如Cardinality。
analyze table
能优化索引存储,使索引更好工作.可每周或每天凌晨运行一次。
值得注意的地方
mysql在查询时,若数据大于整张表的20%,则会放弃索引
参考书籍
高性能MySQL: https://book.douban.com/subject/23008813/
MySQL技术内幕: https://book.douban.com/subject/5373022/
MySQL的InnoDB存储引擎行锁是加在索引上的,所以只当增删改查操作是通过索引找到指定数据行的时候,才能对相应数据行的索引加锁,否则只能对整个表加表锁,表共享读锁或表独占写锁。
当一个事务不经过索引查询数据,即顺序读取(全表扫描)时,先获取表的意向共享锁,然后对表添加共享读锁,阻止其他事务对表的更新,新增和删除操作,但不影响查询操作,共享读锁之间是兼容的。
当一个事务不经过索引更新,删除数据,即全表扫描符合条件的数据行时,先获取表的意向独占锁,然后对表添加独占写锁,在执行更新,删除时阻止其他事务对表的读及写操作。
当一个事务使用索引去查询数据,即随机读取时,先获得表的意向共享锁,然后对符合条件的的索引区间加共享读锁(聚集索引肯定会加锁,若用到了非聚集索引一样加锁),共享读锁之间是兼容的,因此不影响其他事务对被锁数据行的访问。当其他事务想要修改,删除加锁的数据行时,若未使用索引则在获取表独占写锁时会失败。若使用索引检索这些数据行,则可能会在非聚集索引处被阻塞(查询事务和修改事务使用同一个索引检索数据行),也可能在聚集索引处被阻塞(通过非聚集索引查询到聚集索引的键,通过此键查询到相应的聚集索引,同时读到数据航,这是读和写,写和写之间的事务串行化保证),只能等待查询事务释放索引区间的共享读锁,然后执行更新,删除操作。当一个事务想要将新的数据行插入到被加锁的数据行中,也需要等待共享读锁的释放。因为InnoDB实现了间隙锁机制,即当一个事务按一个条件(id < 10,id列含有索引)加锁数据行时,其他事务不能在锁释放前将符合此条件的数据行(id = 5)插入到表中,此机制一定程度防止了幻读的出现。猜测实现机制:前一个事务对数据行的索引加了锁(聚集索引和非聚集索引),其他的事务插入数据时,需要新增聚集/非聚集索引,但是此时符合条件的聚集/非聚集索引区间已经被加锁,不能实时插入索引,需要等到索引区间的锁被释放,这个可能是间隙锁的实现原理。
当一个事务通过索引去更新,删除数据行时,先获取表的意向排他锁,然后对符合条件的数据行的索引加锁(聚集/非聚集),阻止其他事务对被锁数据行的读,写。同理实现间隙锁。
Django的部署有多种方式,采用Nginx+uWSGI的方式是最常见的一种方式。在这种方式中,将Nginx作为服务器前端,接收Web的所有请求,统一管理请求。Nginx自己处理所有静态请求,所有非静态请求通过uWSGI传递给Django,由Django来进行处理,从而完成一次Web请求。
环境:Python(3.5.2)、Django(1.11.6)
root@787c084a44e4:~# apt-get install -y python3-pip
root@787c084a44e4:~# python3 -m pip install uWSGI
root@787c084a44e4:~# python3 -m pip install Django
root@787c084a44e4:~# apt-get install -y nginx
新建文件/root/web/uwsgi.ini
[uwsgi]
# 监听IP和端口
socket = 127.0.0.1:9090
# 项目主目录
chdir = /root/web/Django
# uwsgi文件路径
module = Django.wsgi:application
# 允许主进程存在
master = True
# 开启的进行数
workers = 1
# 服务器退出时自动清楚环境
vacuum = True
# 设置工作进程请求上限
max-requests = 1000
# 记录主进行的pid
pidfile = /var/uwsgi.pid
# 使进程在后台运行
daemonize = /var/uwsgi.log
新建文件/etc/nginx/sites-
enabled/django.conf
# nginx需要连接的后端代理
upstream django {
server 127.0.0.1:9090;
}
# 虚拟主机配置
server {
# 监听端口
listen 8080;
# 域名
server_name 127.0.0.1;
# 编码
charset utf-8;
# 静态文件路径
location /static {
alias /root/web/Django/static;
}
# 将动态请求转发到uwsgi运行的django程序
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params;
}
}
修改/etc/nginx/nginx.conf文件,user www-data修改为user root
运行工程
root@787c084a44e4:~/web# uwsgi --ini uwsgi.ini & nginx
访问地址http://127.0.0.1:8080/list,数据和页面css样式正常
修改Django/Django/settings.py文件
ALLOWED_HOSTS = ["*"]
Nginx使用www-data用户运行,无web目录读取权限,修改/etc/nginx/nginx.conf文件,user www-data修改为user root
今天在docker中启动jenkins容器时,按照官方文档中的方法执行:
docker run -p 8080:8080 -p 50000:50000 -v /your/home:/var/jenkins_home jenkins
遇到了一个权限为题,报错为:
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied
原因是Jenkins镜像内部使用的用户是jenkons,但是我们启动容器时的账号是root,导致没有权限操作内部目录,我们可以稍微改一下上面的命令:
docker run -p 8080:8080 -p 50000:50000 -v /your/home:/var/jenkins_home -u 0 jenkins
这样就启动成功了。
这命令的意思是覆盖容器中内置的帐号,该用外部传入,这里传入0代表的是root帐号Id。这样再启动的时候就应该没问题了。