Ansible 部署 Redis 主从
Ansible 部署 Redis 主从
一、安装ansible服务工具
在安装服务之前先添加epel的yum源,因为ansible的安装依赖epel源
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum makecache
yum -y install ansible
ansible作为一款自动化软件工具,不需要修改配置文件就可以直接启动 ansible的目录结构:
/etc/ansible/ansible.cfg --- ansible服务配置文件
/etc/ansible/hosts --- 主机清单文件 定义可以管理的主机信息
/etc/ansible/roles --- 角色目录
二、创建roles角色目录
官方地址:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
官方的目录定义:
[root@master1 /etc/ansible/roles]# tree
.
├── nfs #角色名称
│ ├── files #存放需要copy的文件
│ ├── handlers #触发任务剧本
│ ├── tasks #具体任务剧本
│ ├── templates #模版文件
│ └── vars #存放变量文件
1.创建目录
根据官方的目录规划,依次创建目录:
mkdir redis_cluster
cd redis_cluster/
mkdir files handlers tasks templates vars
cd files/
mkdir redis_{63{79,80},cmd}
mkdir redis_63{79,80}/{conf,logs,pid}
2.将redis的二进制文件复制到redis_cmd目录下
mkdir /opt/cluster/redis_cluster/src
cd /opt/cluster/redis_cluster/src
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
tar xf redis-5.0.7.tar.gz -C /opt/cluster/redis_cluster/
# 打包
cd /opt/cluster/redis_cluster/redis-5.0.7/src/
make
cp -a redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-server /etc/ansible/roles/redis_cluster/files/redis_cmd/
3.生成ssh免交互
# 产生公私密钥对(已经生成了)
ssh-keygen
# 将本地的公钥上传到远程服务器 (默认 22 ssh端口号,如需更改,添加 -p xxxx)
使用 ssh-copy-id username@your-server-ip 命令
# 输入远程服务器的密码
4.编写主机清单
vim /etc/ansible/hosts
...
[redis-cluster]
192.168.2.246
5.配置文件jinja模版
- 主节点配置模板
vim /etc/ansible/roles/redis_cluster/templates/redis_6379.conf.j2
bind {{ansible_facts.eth0.ipv4.address}}
port 6379
daemonize yes
pidfile "/opt/cluster/redis_cluster/redis_6379/pid/redis_6379.pid"
logfile "/opt/cluster/redis_cluster/redis_6379/logs/redis_6379.log"
dbfilename "redis_6379.rdb"
dir "/data/cluster/redis_cluster/redis_6379/"
appendonly yes
appendfilename "redis.aof"
appendfsync everysec
cluster-enabled yes
cluster-config-file nodes_6379.conf
cluster-node-timeout 15000
- 从节点配置模版
vim /etc/ansible/roles/redis_cluster/templates/redis_6380.conf.j2
bind {{ansible_facts.eth0.ipv4.address}}
port 6380
daemonize yes
pidfile "/opt/cluster/redis_cluster/redis_6380/pid/redis_6380.pid"
logfile "/opt/cluster/redis_cluster/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/cluster/redis_cluster/redis_6380/"
appendonly yes
appendfilename "redis.aof"
appendfsync everysec
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
6.配置启动脚本
- 主节点启动脚本
vim /etc/ansible/roles/redis_cluster/templates/redis-master.service.j2
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/redis-server /opt/cluster/redis_cluster/redis_6379/conf/redis_6379.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h {{ansible_facts.eth0.ipv4.address }} -p 6379 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
- 从节点启动脚本
vim /etc/ansible/roles/redis_cluster/templates/redis-slave.service.j2
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/redis-server /opt/cluster/redis_cluster/redis_6380/conf/redis_6380.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h {{ ansible_facts.eth0.ipv4.address}} -p 6380 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
7.tasks清单
vim /etc/ansible/roles/redis_cluster/tasks/main.yaml
- name: 01-create_group
group:
name: redis
gid: 777
- name: 02-create_user
user:
name: redis
group: redis
uid: 777
shell: /sbin/nologin
create_home: no
- name: 03_copy_cmd
copy:
src: redis_cmd/
dest: /usr/local/bin/
mode: '0755'
- name: 04_copy_conf
copy:
src: "{{ item }}"
dest: /opt/cluster/redis_cluster/
owner: redis
group: redis
loop:
- redis_6380
- redis_6379
- name: 05_create_data
file:
dest: "/data/cluster/redis_cluster/{{ item }}"
state: directory
owner: redis
group: redis
loop:
- redis_6379
- redis_6380
- name: 06_copy_conf
# ignore_errors: yes
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
backup: yes
with_items:
- { src: 'redis_6379.conf.j2', dest: '/opt/cluster/redis_cluster/redis_6379/conf/redis_6379.conf' }
- { src: 'redis_6380.conf.j2', dest: '/opt/cluster/redis_cluster/redis_6380/conf/redis_6380.conf' }
- { src: 'redis-master.service.j2', dest: '/usr/lib/systemd/system/redis-master.service' }
- { src: 'redis-slave.service.j2', dest: '/usr/lib/systemd/system/redis-slave.service' }
- name: 07_start_redis_service
ignore_errors: yes
systemd:
name: "{{ item }}"
state: started
daemon_reload: yes
loop:
- redis-master
- redis-slave
notify:
- restart redis-master
- restart redis-slave
8.handles清单
vim /etc/ansible/roles/redis_cluster/handlers/main.yaml
- name: restart redis-master
service:
name: redis-master
state: restarted
- name: restart redis-slave
service:
name: redis-slave
state: restarted
9.执行任务清单
vim /etc/ansible/redis_cluster.yaml
- hosts: redis-cluster
roles:
- redis_cluster
10.检查剧本语法
ansible-playbook --syntax-check /etc/ansible/redis_cluster.yaml
11.模拟执行剧本
ansible-playbook -C /etc/ansible/redis_cluster.yaml
12.执行剧本
ansible-playbook /etc/ansible/redis_cluster.yaml
CSRF-SSRF-XML-XXE
- 目录:
CSRF
XML 基础知识
XML 外部实体注入(XXE)
SSRF
CSRF
从新人角度来区分:
- XSS: 利用用户对站点的新人
- CSRF: 利用站点对已经认证用户的信任
常见攻击方式:
结合社工在身份认证会话过程中实现攻击 修改账号密码、个人信息、(email、收货地址)发送伪造的业务请求(网银,购物,投票) 关注他人社交帐号,推送博文 在用户非自愿,不知情的情况下提交请求
业务逻辑漏洞
对关键操作缺少确认机制 自动扫描程序无法发现此类漏洞
漏洞利用条件
被害用户已经完成身份认证
新请求的提交不需要重新身份认证或确认机制
攻击者必须了解web app请求的参数构造
诱使客户触发攻击的指令
Burp suite CSRF PoC generator
Post / Get 方法
自动扫描程序检测CSRF漏洞方法
在请求和响应过程中检查是否存在anti-CSRF token
检测服务器是否验证anti-CSRF token
检测referrer头是否可以伪造
CSRF 漏洞防御
- Captcha
- anti-CSRF token
- Referrer头
- 降低会话超时时间
XML 简介
XML 指可扩展标记语言 (extensible Markup Language) 。
XML被设计用来传输和存储数据。(HTML被设计用来显示数据。)
XML是-种很像HTML的标记语言。
XML标签没有被预定义。需要自行定义标签。
XML被设计为具有自我描述性。
Xml是W3C的推荐标准。
XML作用
- XML 把数据从HTML分离
- XML简化数据共享
- XML简化数据传输
- XML简化平台变更
XML树结构
XML文档形成了一种树结构,它从"根部"开始,然后扩展到"枝叶"。
XML文档使用简单的具有自我描述性的语法:
<?xml version="1.0" encoding="UTF-8"\?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
第一行是XML声明。它定义XML的版本(1.O)和所使用的编码下一行描述文档的根元素<note>
接下来4行描述根的4个子元素(to, from, heading 以及body)最后一行定义根元素的结尾: </note>
- XML文档必须包含根元素。该元素是所有其他元素的父元素。XML文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。
- 所有的元素都可以有子元素。
- 父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。相同层级上的子元素成为同胞(兄弟或姐妹)。
- 所有的元素都可以有文本内容和属性(类似HTML中) 。
XML语法规则
1.XML文档必须有根元素
2.XML声明文件的可选部分,如果存在需要放在文档的第一行
<?xml version="1.0" encoding="utf-8"?>3.所有的XML元素都必须有一个关闭标签
</>4.XML 标签对大小写敏感
5.XML必须正确嵌套
6.XML属性值必须加引号
7.用实体引用来代替
"<"等特殊字符在XML中,有5个预定义的实体引用:  (空格)  ;
< < less than <
> > greater than >
& & ampersand &
' ' apostrophe '
" " quotation mark "8.在XML中编写注释的语法与HTML的语法很相似。
9.在XML中,文档中的空格不会被删减。
XML元素
XML元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。
一个元素可以包含:
- 其他元素
- 文本
- 属性
- 或混合以上所有...
XML命名规则
XML元素必须遵循以下命名规则:
- 名称可以包含字母、数字以及其他的字符
- 名称不能以数字或者标点符号开始
- 名称不能以字母xml(或者XML、Xml等等)开始
- 名称不能包含空格
- 可使用任何名称,没有保留的字词。
命名习惯:
1.使名称具有描述性。使用下划线的名称也很不错:<first_name> ,<last_name>
2.名称应简短 和 简单,比如 : <book_title> ,而不是∶<the_title_of_the_book>。
3.避免"-"字符。如果按照这样的方式进行命名: "first-name",一些软件会认为想要从first里边减去name。
4.避免"."字符。如果按照这样的方式进行命名: "first.name",一些软件会认为"name"是对象"first"的属性。
5.避免":"字符。冒号会被转换为命名空间来使用。
6.xml文档经常有一个对应的数据库,其中的字段会对应xml文档中的元素。有一个实用的经验,即使用数据库的命名规则来命名xml文档中的元素.
7.在xml中,éoa等非英语字母是完全合法的,不过需 要留意,软件供应商如不支持这些字符时可能出现的问题.
XML元素是可扩展的
PS:可以在不间断应用程序的情况下进行扩展
比如下面的
<note>
<to>Tove</to>
<from>Jani</from>
<body>Don't forget me this weekend!</body>
</note>
扩展为:
<note>
<date>2008-01-10</date>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
XML 属性
- XML元素具有属性,类似HTML。
- 属性(Attribute)提供有关元素的额外信息。
- XML属性必须加引号
- 属性值必须被引号包围,不过单引号和双引号均可使用。
person sex="female">
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
<person>
<sex>female</sex>
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
在第一个实例中,sex是一个属性。在第二个实例中,sex是一个元素。这两个实例都提供相同的信息。
XML 元素vs属性
在HTML 中,属性用起来很便利,但是在XML中,应该尽量避免使用属性。如果信息感觉起来很像数据,那么请使用元素吧
因使用属性而引起的一些问题:
- 属性不能包含多个值(元素可以)
- 属性不能包含树结构(元素可以)
- 属性不容易扩展(为未来的变化)
属性难以阅读和维护。请尽量使用元素来描述数据。而仅仅使用属性来提供与数据无关的信息。
良好的XML文档
形式良好的XML文档拥有正确的语法。
在前面的章节描述的语法规则:
- XML文档必须有一个根元素
- XML元素都必须有一个关闭标签
- XML标签对大小写敏感
- XML元素必须被正确的嵌套
- XML属性值必须加引号
可以通过DTD或XML Schema (DTD的替代者)验证XML是合法的XML
DTD
DTD(文档类型定义)的作用是定义XML文档的合法构建模块。
DTD可被成行地声明于XML文档中,也可作为一个外部引用。
内部的DOCTYPE声明
假如DTD被包含在XML源文件中,它应当通过下面的语法包装在一个DOCTYPE声明中:
<?xml version="1.0"\?>
<!DOCTYPE note [ <!-- 在这里添加 -->
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]
<note>
<to>Tove</to>
<from>Jani</from>
<body>Don't forget me this weekend!</body>
</note>
外部文档声明
假如DTD位于XML源文件的外部,那么它应通过下面的语法被封装在一个DOCTYPE定义中:
<!DOCTYPE root-element sYSTEM "filename">
这个XML文档和上面的XML文档相同,但是拥有一个外部的DTD:
<?xml version="1.0"\?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
这是包含DTD的"note.dtd"文件:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to(#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
为什么使用DTD
通过DTD,每一个XML文件均可携带一个有关其自身格式的描述。
通过DTD,独立的团体可一致地使用某个标准的DTD来交换数据。
应用程序也可使用某个标准的DTD来验证从外部接收到的数据。
还可以使用DTD来验证自身的数据。
PCDATA
了 解一下就好
PCDATA的意思是被解析的字符数据(parsed character data) 。可把字符数据想象为XML元素的开始标签与结束标签之间的文本。 PCDATA是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。 文本中的标签会被当作标记来处理,而实体会被展开。 不过,被解析的字符数据不应当包含任何&、
<或者>字符;需要使用&、<以及>实体来分别替换它们。
CDATA
CDATA的意思是字符数据(character data) 。
CDATA是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
实体
如果在XML文档中需要频繁使用某一条数据,我们可以预先给这个数据起一个别名。即一个ENTITY,然后再在文档中调用它。
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
实体引用是对实体的引用。
实体可在内部或外部进行声明。
XML基本语法
内部实体
<!ENTITY 实体名称"实体的值">
<?xml version="1.0"\?>
<!DOCTYPE note[
<!ELEMENT note (name)>
<!ENTITY hack3r "Hu3sky">
]>
<note>
<name>&hack3r;</name>
</note>
<!-- 定义一个hack3r值为"Hu3sky"·就可以在XML任何地方引用。-->
外部参数实体
<?xml version="1.0" encoding="utf-8"\?>
<!DOCTYPE a [
<!ENTITY % name SYSTEM "file:/l/etc/passwd">
%name;
]>
实体

补充:
参数实体只能在DTD文件中被引用,其他实体在XML文档内引用
一般实体指代的是将来XML数据文档要用到的文本或数据,而参数实体是在DTD文档内定义的一种DTD信息,所代表的是DTD定义的一部分,不能在XML文档中使用,也不能在DTD中定义.
XXE
XXE全称XML External Entity Injection·也就是XML外部实体注入攻击﹐漏洞是对非安全的外部实体数据进行处理时引发的安全问题。
XML作为一种使用较为广泛的数据传输格式﹐很多应用程序都包含有处理xml数据的代码﹐默认情况下﹐许多过时的或配置不当的XML处理器都会对外部实体进行引用。
如果攻击者可以上传XML文档或者在XML文档中添加恶意内容﹐通过易受攻击的代码﹑依赖项或集成·就能够攻击包含缺陷的XML处理器·XXE漏洞的出现和开发语言无尖﹐只要是应用程序中对xml数据做了解析﹐而这些数据又受用户控制·那么应用程序都可能受到XXE攻击。
防御XML注入攻击
一、使用开发语言提供的禁用外部实体的方法
1.PHP:
libxml_disable_entity_loader(true);
2.JAVA
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
3.Python:
from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
二、过滤用户提交的XML数据
xxe漏洞存在是因为XML解析器解析了用户发送的不可信数据·然而﹐要去校验DTD(document type definition)中SYSTEM标识符定义的数据﹐并不容易·也不大可能·大部分的XML解析器默认对于XXE攻击是脆弱的。
因此·最好的解决办法就是配置XML处理器去使用本地静态的DTD·不允许XML中含有任何自己声明的DTD·通过设置相应的属性值为false ·XML外部实体攻击就能够被阻止·因此·可将外部实体·参数实体和内联DTD都被设置为false·从而避免基于XXE漏洞的攻击。
SSRF
SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由恶意访问者构造形成由服务端发起请求的一个安全漏洞。
一般情况下﹐SSRF访问的目标是从外网无法访问的内部系统·(正是因为它是由服务端发起的﹐所以它能够请求到与它相连而与外网隔离的内部系统)
SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制·比如从指定URL地址获取网页文本内容﹐加载指定地址的图片·下载等等。
PHP中可能导致SSRF的函数
- file_get_contents()
- fsockopen()
- curl_exec()
curl
curl_exec()curl是利用URL语法在命令行方式下工作的开源文件传输工具。它被广泛应用在Unix、多种Linux发行版中,并且有DOS和Win32、Win64下的移植版本。
curl支持很多协议,有FTP, FTPS, HTTP, HTTPS, GOPHER,TELNET, DICT,FILE以及LDAP
- curl_exec 执行一个cURL会话
- curl_init 初始化一个cURL会话
- curl_setopt 设置一个cURL传输选项。
<?php
//创建一个新cURL资源
$ch = curl_init();
//设置URL和相应的选项
curl_setopt($ch, CURLOPT_URL, "https://www.baidu.com/");
curl_setopt($ch, CURLOPT_HEADER,0);
//抓取URL并把它传递给浏览器
curl_exec($ch);
//关闭cURL资源,并且释放系统资源curl_close($ch);
\?>
CSRF和SSRF对比
CSRF(Cross-site request forgery)跨站请求伪造
漏洞发生于客户端 诱使客户端发送攻击者构造的请求
SSRF(Server-Side Request Forgery:服务器端请求伪造)
漏洞发生于服务端 强制服务端发送攻击者构造的请求

SSRF漏洞的危害
- 1·扫描内部网络(EingerPrint )
- 2·向内部任意主机和任意端口发送精心构造的数据包( payload )
- 3·DOS(请求大文件﹐始终保持连接Keep-Alive Always )
- 4·暴力穷举( user/dirs/files )