【工作】Nginx 实现域名的登录验证功能

背景说明

研发有个需求,访问公司某个域名下的某个url时候需要认证,只有输入正确的用户密码才允许访问web内容。

实现思路

Nginx服务中的”ngx_http_auth_basic_module”模块可以实现此要求,默认情况下编译安装完nginx后,就已经安装启用了ngx_http_auth_basic_module模块,如果不需要这个模块,可以加上 –without-http_auth_basic_module关闭。

ngx_http_auth_basic_module模块指令:

语法: auth_basic string | off;
默认值: auth_basic off;
作用:默认表示不开启认证,后面如果跟上字符,这些字符会在弹窗中显示。
配置段: http, server, location, limit_except

语法: auth_basic_user_file file;
默认值: 无
作用:指定密码文件的位置,可以是相对路径或者绝对路径
配置段: http, server, location, limit_except

实现过程

下面以我的网站www.jiagoumi.com来演示此功能的实现过程,需求是仅当访问http://www.jiagoumi.com/test/时候输入密码才能访问

1. 使用openssl生成密码文件

# printf "test:$(openssl passwd -crypt 123123)n" >> /usr/local/nginx/conf/htpasswd.auth
[root@160719 nginx]# cat /usr/local/nginx/conf/htpasswd
test:bFJVr/zQWK60.

2.修改虚拟主机配置文件

下面红色部分为添加实现的代码

server {
    listen       80;
    server_name    www.jiagoumi.com;
    access_log    logs/www.jiagoumi.com.access.log;
    error_log     logs/www.jiagoumi.com.error.log;

    location /test {
     auth_basic "Authorization Required";
     auth_basic_user_file /usr/local/nginx/conf/htpasswd.auth;
     index  index.php index.html index.htm;
     root   /data/nginx/site/www.jiagoumi.com;
     }

    location /
    {
        proxy_set_header        Host  $host;
        proxy_set_header        X-Real-IP  $remote_addr;
        proxy_set_header        REMOTE-HOST $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass              http://192.168.1.1:8080;
    }

验证配置文件,重启Nginx服务:

# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/nginx.conf test is successful

# /usr/local/nginx/sbin/nginx -s reload

3.验证效果

访问http://www.jiagoumi.com/test/会提示输入密码,输入上面创建的账号密码即可登录查看内容。

注意:此功能需要使用IE兼容模式访问,使用chrome内核的浏览器无法正常访问。

未分类

Apache优化:修改最大并发连接数

Apache是一个跨平台的web服务器,由于其简单高效、稳定安全的特性,被广泛应用于计算机技术的各个领域。现在,Apache凭借其庞大的用户数,已成为用户数排名第一的web服务器。

尽管如此,在实际的生产环境中,我们仍然不可能直接使用默认配置的Apache来充当服务器。毕竟,为了更充分合理地利用Apache服务器,我们都应该根据自己的实际需要对Apache的默认配置作出一些必要的调整。而针对Apache的优化配置过程中,修改Apache的最大并发连接数就显得尤为重要。

在修改Apache的最大并发连接数之前,我们需要预先了解一些Apache的相关知识。

众所周知,Apache是一个跨平台的、采用模块化设计的服务器。为了应对不同的平台和不同的环境产生的各种不同的需求,也为了在具体的平台或环境下达到最佳的效果,Apache在web服务器的基础功能方面(端口绑定、接收请求等)也同样采用了模块化设计,这个Apache的核心模块就叫做多路处理模块(Multi-Processing Module,简称MPM)。

Apache针对不同的操作系统提供了多个不同的MPM模块,例如:mpm_beos、mpm_event、mpm_netware、mpmt_os2、mpm_prefork、mpm_winnt、mpm_worker。如果条件允许,我们可以根据实际需求将指定的MPM模块编译进我们自己的Apache中(Apache的源码是开放的,允许用户自行编译)。不过,如果在编译时我们没有选择,Apache将按照如下表格根据不同的操作系统自行选择对应的MPM模块,这也是Apache针对不同平台推荐使用的MPM模块。

未分类

mpm_event模块可以看作是mpm_worker模块的一个变种,不过其具有实验性质,一般不推荐使用。

当然,Apache在其官方网站上也提供了根据不同操作系统已经编译好对应MPM模块的成品Apache。你可以点击此处进入Apache官方网站下载。

此外,如果我们想要知道某个Apache内部使用的是何种MPM模块,我们可以以命令行的方式进入Apache安装目录bin,然后键入命令httpd -l,即可查看到当前Apache内部使用的何种MPM模块。

未分类

由于在平常的开发工作中,BeOS、NetWare、OS/2等操作系统并不常见,这里我们主要针对Windows和Unix/Linux操作系统上的MPM模块进行讲解。在Windows和Unix/Linux操作系统上,MPM模块主要有mpm_winnt、mpm_prefork、mpm_worker三种。

mpm_prefork模块

mpm_prefork模块主要应用于Unix/Linux平台的Apache服务器,其主要工作方式是:当Apache服务器启动后,mpm_prefork模块会预先创建多个子进程(默认为5个),当接收到客户端的请求后,mpm_prefork模块再将请求转交给子进程处理,并且每个子进程同时只能用于处理单个请求。如果当前的请求数将超过预先创建的子进程数时,mpm_prefork模块就会创建新的子进程来处理额外的请求。Apache总是试图保持一些备用的或者是空闲的子进程用于迎接即将到来的请求。这样客户端的请求就不需要在接收后等候子进程的产生。

由于在mpm_prefork模块中,每个请求对应一个子进程,因此其占用的系统资源相对其他两种模块而言较多。不过mpm_prefork模块的优点在于它的每个子进程都会独立处理对应的单个请求,这样,如果其中一个请求出现问题就不会影响到其他请求。同时,mpm_prefork模块可以应用于不具备线程安全的第三方模块(比如PHP的非线程安全版本),且在不支持线程调试的平台上易于调试。此外,mpm_prefork模块还具有比mpm_worker模块更高的稳定性。

mpm_worker模块

mpm_worker模块也主要应用于Unix/Linux平台的Apache服务器,它可以看作是mpm_prefork模块的改进版。mpm_worker模块的工作方式与mpm_prefork模块类似。不过,由于处理相同请求的情况下,基于进程(例如mpm_prefork)比基于线程的处理方式占用的系统资源要多。因此,与mpm_prefork模块不同的是,mpm_worker模块会让每个子进程创建固定数量的服务线程和一个监听线程,并让每个服务线程来处理客户端的请求,监听线程用于监听接入请求并将其传递给服务线程处理和应答。Apache总是试图维持一个备用或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。

与mpm_prefork模块相比,mpm_worker模块可以进一步减少系统资源的开销。再加上它也使用了多进程,每个进程又有多个线程,因此它与完全基于线程的处理方式相比,又增加了一定的稳定性。

mpm_winnt模块

mpm_winnt模块是专门针对Windows操作系统而优化设计的MPM模块。它只创建一个单独的子进程,并在这个子进程中轮流产生多个线程来处理请求。

修改MPM模块配置

在对Apache的MPM模块具备一定了解后,我们就可以针对不同的MPM模块来修改Apache的最大并发连接数配置了。

1. 启用MPM模块配置文件

在Apace安装目录/conf/extra目录中有一个名为httpd-mpm.conf的配置文件。该文件主要用于进行MPM模块的相关配置。不过,在默认情况下,Apache的MPM模块配置文件并没有启用。因此,我们需要在httpd.conf文件中启用该配置文件,如下所示:

# Server-pool management (MPM specific)
Include conf/extra/httpd-mpm.conf (去掉该行前面的注释符号"#")

2. 修改MPM模块配置文件中的相关配置

在启动MPM模块配置文件后,我们就可以使用文本编辑器打开该配置文件,我们可以看到,在该配置文件中有许多配置节点,如下图所示:

未分类

此时,我们就需要根据当前Apache服务器所使用的MPM模块,来修改对应节点下的参数配置。首先,我们来看看mpm_winnt模块下的默认配置:

#由于mpm_winnt模块只会创建1个子进程,因此这里对单个子进程的参数设置就相当于对整个Apache的参数设置。

<IfModule mpm_winnt_module>
ThreadsPerChild      150 #推荐设置:小型网站=1000 中型网站=1000~2000 大型网站=2000~3500
MaxRequestsPerChild    0 #推荐设置:小=10000 中或大=20000~100000
</IfModule>

对应的配置参数作用如下:

ThreadsPerChild

每个子进程的最大并发线程数。

MaxRequestsPerChild

每个子进程允许处理的请求总数。如果累计处理的请求数超过该值,该子进程将会结束(然后根据需要确定是否创建新的子进程),该值设为0表示不限制请求总数(子进程永不结束)。

该参数建议设为非零的值,可以带来以下两个好处:

  1. 可以防止程序中可能存在的内存泄漏无限进行下去,从而耗尽内存。

  2. 给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。

注意:在以上涉及到统计请求数量的参数中,对于KeepAlive的连接,只有第一个请求会被计数。

接着,我们再来看看mpm_perfork模块和mpm_worker模块下的默认配置:

#mpm_perfork模块

<IfModule mpm_prefork_module>
StartServers          5 #推荐设置:小=默认 中=20~50 大=50~100
MinSpareServers       5 #推荐设置:与StartServers保持一致
MaxSpareServers      10 #推荐设置:小=20 中=30~80 大=80~120 
MaxClients          150 #推荐设置:小=500 中=500~1500 大型=1500~3000
MaxRequestsPerChild   0 #推荐设置:小=10000 中或大=10000~500000
(此外,还需额外设置ServerLimit参数,该参数最好与MaxClients的值保持一致。)
</IfModule>
#mpm_worker模块

<IfModule mpm_worker_module>
StartServers          2 #推荐设置:小=默认 中=3~5 大=5~10
MaxClients          150 #推荐设置:小=500 中=500~1500 大型=1500~3000
MinSpareThreads      25 #推荐设置:小=默认 中=50~100 大=100~200
MaxSpareThreads      75 #推荐设置:小=默认 中=80~160 大=200~400 
ThreadsPerChild      25 #推荐设置:小=默认 中=50~100 大型=100~200
MaxRequestsPerChild   0 #推荐设置:小=10000 中或大=10000~50000
(此外,如果MaxClients/ThreadsPerChild大于16,还需额外设置ServerLimit参数,ServerLimit必须大于等于 MaxClients/ThreadsPerChild 的值。)
</IfModule>

对应的配置参数作用如下:

StartServers

启动Apache时创建的子进程数。

MinSpareServers

处于空闲状态的最小子进程数。

所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于MinSpareServers,那么Apache将以最大每秒一个的速度产生新的子进程。只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。

MaxSpareServers

处于空闲状态的最大子进程数。

只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成MinSpareServers+1。

MaxClients

允许同时连接的最大请求数量。

任何超过MaxClients限制的请求都将进入等待队列,直到达到ListenBacklog指令限制的最大值为止。

对于非线程型的MPM(也就是mpm_prefork),MaxClients表示可以用于处理客户端请求的最大子进程数量,默认值是256。要增大这个值,你必须同时增大ServerLimit。

对于线程型或者混合型的MPM(也就是mpm_beos或mpm_worker),MaxClients表示可以用于处理客户端请求的最大线程数量。线程型的mpm_beos的默认值是50。对于混合型的MPM默认值是16(ServerLimit)乘以25(ThreadsPerChild)的结果。因此要将MaxClients增加到超过16个进程才能提供的时候,你必须同时增加ServerLimit的值。

MinSpareThreads

处于空闲状态的最小线程数。

不同的MPM对这个指令的处理是不一样的:

mpm_worker的默认值是75。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太少,子进程将产生新的空闲线程。mpm_netware的默认值是10。既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。mpm_beos和mpmt_os2的工作方式与mpm_netware差不多,mpm_beos的默认值是1;mpmt_os2的默认值是5。

MaxSpareThreads

处于空闲状态的最大线程数。

不同的MPM对这个指令的处理是不一样的:

mpm_worker的默认值是250。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太多,子进程将杀死多余的空闲线程。mpm_netware的默认值是100。既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。mpm_beos和mpmt_os2的工作方式与mpm_netware差不多,mpm_beos的默认值是50;mpmt_os2的默认值是10。

备注:ServerLimit表示Apache允许创建的最大进程数。 值得注意的是,Apache在编译时内部有一个硬限制ServerLimit 20000(对于mpm_prefork模块为ServerLimit 200000)。你不能超越这个限制。
使用这个指令时要特别当心。如果将ServerLimit设置成一个高出实际需要许多的值,将会有过多的共享内存被分配。如果将ServerLimit和MaxClients设置成超过系统的处理能力,Apache可能无法启动,或者系统将变得不稳定。

注意:在配置相关参数时,请先保证服务器具备足够的硬件性能(例如:CPU、内存等)。 如果发现自启动后,随着服务器的运行时间增加,服务器的内存占用也随之增加,可能是程序中出现内存泄露,请向下调整参数MaxRequestsPerChild的值以降低内存泄露带来的影响,然后尽快找出程序中的问题之所在。

[译]Linux:25个有用的iptables防火墙规则

管理网络流量是系统管理员需要处理的最棘手的工作之一。

管理员配置防火墙时需要同时满足系统和用户对于传出和传入连接的要求,而且要避免系统遭受攻击。

这就是iptables有用的地方。iptables是一个linux命令行防火墙,它允许系统管理员通过一系列可配置的规则来控制传出和传入的流量。

iptables使用一系列具有链结构的表,这些链包含内建的规则或用户定义的规则。多亏于此,系统管理员可以恰当地过滤系统的网络流量。

iptables中有以下三种类型的表:

  • FILTER表,默认的表,包含以下三种内建链:
    • INPUT链,发给本地sockets的包
    • FORWARD链,经由系统发送的包
    • OUTPUT链,本地生成并发出的包
  • NAT表,当一个包试图创建新连接时将访问该表,该表包含以下内建链:
    • PREROUTING链,更改刚接收到的包
    • OUTPUT链,更改本地产生的包
    • POSTROUTING链,更改即将发出的包
  • MANGLE表,用于包的更改:
    • PREROUTING链:更改传入连接
    • OUTPUT链:更改本地产生的包
    • INPUT链:更改传入的包
    • POSTROUTING链:更改即将发出的包
    • FORWARD链:更改经过的包

在这篇文章中,你将会看到一些有用的命令,帮助你使用iptables来管理你的Linux防火墙。

1. 开始/停止/重启iptables防火墙

首先,你应该知道如何在不同发行版的Linux系统中管理iptables服务。

基于SystemD的linux发行版

------------ On Cent/RHEL 7 and Fedora 22+ ------------
# systemctl start iptables
# systemctl stop iptables
# systemctl restart iptables

基于SysVinit的linux发行版

------------ On Cent/RHEL 6/5 and Fedora ------------
# /etc/init.d/iptables start
# /etc/init.d/iptables stop
# /etc/init.d/iptables restart

2. 查看所有iptables规则

# iptables -L -n -v

输出示例:

Chain INPUT (policy ACCEPT 1129K packets, 415M bytes)
pkts bytes target prot opt in out source destination 
0 0 ACCEPT tcp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 ACCEPT udp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT tcp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
0 0 ACCEPT udp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination 
0 0 ACCEPT all -- * lxcbr0 0.0.0.0/0 0.0.0.0/0 
0 0 ACCEPT all -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0

Chain OUTPUT (policy ACCEPT 354K packets, 185M bytes)
pkts bytes target prot opt in out source destination

如果你想要查看某个表的规则,可以使用-t选项,后面跟上你想要查看的表。例如,要查看NAT表的规则,可以输入以下命令:

# iptables -t nat -L -v -n

3. 屏蔽某个IP地址

如果你发现一个来自某个IP的异常活动,你可以屏蔽这个IP地址:

# iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

将“xxx.xxx.xxx.xxx”改为想要屏蔽的IP地址。需要注意的是,你有可能会意外屏蔽自己的IP地址。 -A 选项会将规则添加到指定的链中。

如果你只想要屏蔽来自某个IP地址的TCP流量,你可以使用 -p 选项来指定协议。这种情况下命令如下:

# iptables -A INPUT -p tcp -s xxx.xxx.xxx.xxx -j DROP

4. 取消屏蔽某个IP地址

如果你想取消对某个IP地址的屏蔽,可以删除对应的屏蔽规则:

# iptables -D INPUT -s xxx.xxx.xxx.xxx -j DROP

选项 -D 用于从选定的链中删除一条或多条规则,你也可以使用 –delete 选项。

5. 屏蔽某个端口

有时候我们会想要屏蔽基于某个端口的传出或传入连接,这是一个良好的安全措施,当你要设定防火墙时,应该认真考虑这措施。

屏蔽基于某个端口的传出连接:

# iptables -A OUTPUT -p tcp --dport xxx -j DROP

允许基于某个端口的传入连接:

# iptables -A INPUT -p tcp --dport xxx -j ACCEPT

将上面例子中的“xxx”修改为想要屏蔽或允许的端口号。如果你想要屏蔽UDP流量而不是TCP流量,只需简单地将上述规则中的 tcp 修改为 udp 即可。

6. 使用Multiport允许多个端口

你可以通过使用multiport来同时允许多个端口,你可以在下面找到适用于传入和传出的规则:

# iptables -A INPUT  -p tcp -m multiport --dports 22,80,443 -j ACCEPT
# iptables -A OUTPUT -p tcp -m multiport --sports 22,80,443 -j ACCEPT

7. 允许基于某个端口的指定范围的网络

你可能想限制一些基于某个端口的连接访问特定网络。比方说你想要允许基于22端口的传出连接访问192.168.100.0/24网络,可以通过以下命令实现:

# iptables -A OUTPUT -p tcp -d 192.168.100.0/24 --dport 22 -j ACCEPT

8. 屏蔽Facebook网站

有一些雇主喜欢屏蔽员工对于Facebook网站的访问权限,下面是一个屏蔽Facebook流量的示例。

首先找到Facebook使用的IP地址:

# host facebook.com
facebook.com has address 66.220.156.68

# whois 66.220.156.68 | grep CIDR
CIDR: 66.220.144.0/20

接下来你就可以屏蔽Facebook网站了:

# iptables -A OUTPUT -p tcp -d 66.220.144.0/20 -j DROP

注意,Facebook网站使用的IP地址范围可能因国家而异。

9. 设置端口转发

有时你可能想要将某个服务的流量转发到另一个端口,命令如下:

# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j REDIRECT --to-port 2525

以上命令会将所有来自eth0接口的传入流量,由25端口转发到2525端口。你可以根据自己的需要来修改端口号。

10. 屏蔽Apache端口的网络洪水

有些IP地址可能会对网站的web端口请求过多的连接,这可能导致一些问题。要避免这些问题,你可以使用以下规则:

# iptables -A INPUT -p tcp --dport 80 -m limit --limit 100/minute --limit-burst 200 -j ACCEPT

上述命令中 –limit 100/minute 表示将传入连接限制为100个每分钟,–limit-burst 200 表示仅当连接总数达到200个以后才开始限制连接数。

11. 屏蔽传入Ping请求

基于安全考虑,有些系统管理员喜欢屏蔽传入ping请求。虽然威胁并不大,不过了解如何屏蔽这样的请求还是有好处的:

# iptables -A INPUT -p icmp -i eth0 -j DROP

12. 允许loopback权限

loopback权限(来自127.0.0.1的权限)是非常重要的,你应该总是将其设为激活状态。

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A OUTPUT -o lo -j ACCEPT

13. 记录丢弃的网络包

如果你想要记录eth0接口所丢弃的网络包,可以使用以下命令:

# iptables -A INPUT -i eth0 -j LOG --log-prefix "IPtables dropped packets:"

你可以改变 –log-prefix 选项后面所跟的内容。日志将被记录到 /var/log/messages 文件中,你可以通过以下命令来搜索日志:

# grep "IPtables dropped packets:" /var/log/messages

14. 屏蔽某个MAC地址

你可以屏蔽来自特定MAC地址的访问权限:

# iptables -A INPUT -m mac --mac-source 00:00:00:00:00:00 -j DROP

当然,你需要将“00:00:00:00:00:00”改为你想屏蔽的MAC地址。

15. 限制每个IP的并发连接数

如果你不想同一个IP地址在某个端口同时建立太多连接,你可以通过以下方式进行限制:

# iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT

上述命令允许每个客户端同时建立最多3个连接。当然,你可以改变端口号来匹配不同的服务。

16. 搜索IPtables规则

一旦你定义了自己的iptables规则,你可能经常需要进行搜索或修改操作。一种简单的搜索方式如下:

# iptables -L $table -v -n | grep $string

在上述示例中,你需要将 $table 改为你想搜索的表,并将 $string 改为你想搜索的字符串。

示例如下:

# iptables -L INPUT -v -n | grep 192.168.0.100

17. 定义新的链

你可以定义自己的链,并在其中存放自定义的规则。

定义一个链:

# iptables -N custom-filter

现在你可以查看你定义的过滤规则了:

# iptables -L

示例输出:

Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain custom-filter (0 references)
target prot opt source destination

18. 删除所有链或规则

删除所有自定义链:

# iptables -F

清除某个表中的所有链:

# iptables -t nat -F

你可以将“nat”改为想要清除的链所在的表。

19. 保存IPtables规则到文件

如果你想保存你的防火墙规则,可以使用 iptables-save 命令:

# iptables-save > ~/iptables.rules

20. 从文件恢复IPtables规则

如果你想要恢复一个列表的规则,可以使用 iptables-restore 命令:

# iptables-restore < ~/iptables.rules

21. 设置符合PCI的规则

有一些系统管理员可能被要求将服务器按PCI要求进行配置。不同的PCI提供商有许多不同的要求,但也有一些共同的要求。

在很多情况下,你需要拥有多于一个的IP地址。你需要将以下规则应用到网站的IP地址中。请特别注意,使用下面的命令时你应该清楚自己在做什么。

# iptables -I INPUT -d SITE -p tcp -m multiport --dports 21,25,110,143,465,587,993,995 -j DROP

如果你使用cPanel或者类似的控制面板,你可能还需要屏蔽它的端口。示例如下:

# iptables -I in_sg -d DEDI_IP -p tcp -m multiport --dports  2082,2083,2095,2096,2525,2086,2087 -j DROP

注意:为了确保你满足PCI供应商的要求,请认真查看他们的报告,并应用要求的规则。在一些情况下你可能还需要屏蔽基于特定端口的UDP流量。

22. 允许已建立的和相关联的连接

正如网络流量被分为传入和传出,你可能想要允许已建立的和相关联的传入流量。

对于传入连接:

# iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

对于传出连接:

# iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

23. 丢弃无效的包

我们可以将某些网络包标记为无效。一些人可能喜欢记录这些包,但另一些人喜欢丢弃它们。要丢弃无效的包,可以执行以下命令:

# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP 

24. 屏蔽某个网络接口的连接

有些系统可能具有不止一个的网络接口。你可以限制某个网络接口的访问权限,或者屏蔽来自特定IP地址的连接。

例如:

# iptables -A INPUT -i eth0 -s xxx.xxx.xxx.xxx -j DROP

将“xxx.xxx.xxx.xxx”改为你想屏蔽的IP地址。

25. 禁止传出邮件

如果你的系统不应该发送任何电子邮件,你可以屏蔽SMTP传出端口。

示例:

# iptables -A OUTPUT -p tcp --dports 25,465,587 -j REJECT

总结

IPtables是一个强大而又易用的防火墙。学习IPtables的基本使用,对于每个Linux系统管理员而言都是非常重要的。如果你想要了解更多关于iptables命令及其选项的详细内容,建议你阅读它的手册:

# man iptables

centos vsftp下修改默认端口21

常规下21端口容易遭到别人的扫描、带来了一定程度的不安全。所以,最好的就是把21端口修改掉。默认修改为2121

一、修改vsftp的配置文件

vi /etc/vsftpd/vsftpd.conf

在原来的基础上加上:

listen_port=2121
pasv_enable=YES
pasv_min_port=1050
pasv_max_port=1060
pasv_promiscuous=YES

二、修改防火墙规则

如果防火墙开启、并且做了端口限制、请添加这两条规则。

vi /etc/sysconfig/iptables
-A INPUT -p tcp -m state --state NEW -m tcp --dport 1050:1060 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 2121 -j ACCEPT
service iptables restart

三、通过客户端ftp连接(选择被动模式连接)

Linux CentOS 7 重置root用户密码

在Centos 7以前的发行版中,只需要在vmlinuz行末尾添加“1”或“single”后按b重新引导即可。Linux Centos 7系列发行版系统,若是忘记超级用户root密码,破解起来相当费事。而且重置Centos 7 Root密码的方法和Centos 6系列完全不同。

接下来我将以2种解决方案破解Centos 7 Root密码。

第一种解决方案

1. 进入单用户模式

在系统启动读秒的时候,按下任意键,会出现选择内核启动项,选择第一个按下e编辑当前内核。

在以下选项中,添加“rd.break”红色标注部分:

linux16 /vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro cra
shkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet LANG=en_US.UTF-8 rd.break

添加完成,然后按 “ctrl+x” 或 “F10” 启动。

2. 以读写权限挂载文件系统

switch_root # mount -o rw,remount /sysroot/
switch_root # chroot /sysroot/

3. 修改root用户密码

sh-4.2 # echo NewRenwole123 | passwd --stdin root
Changing password for user root.
passwd:all authentication tokens updated successfully.

或:

sh-4.2 # passwd root (输入两次密码回车即可)

4. 重载SElinux并退出单用户模式

sh-4.2 # touch /.autorelabel
sh-4.2 # exit
switch_root # reboot

重新启动后,可以使用新密码 “NewRenwole123” 登录。

第二种解决方案

1. 进入单用户模式

系统启动读秒的时候,按下e编辑当前内核:

linux16 /vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro cra
shkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet LANG=en_US.UTF-8

修改为:

linux16 /vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro cra
shkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap init=/bin/sh

将“rhgb quiet LANG=zh_CN.UTF-8”替换为“init=/bin/sh”,按“ctrl+x”或“F10”引导系统。

2. 挂载并使文件系统为可写

sh-4.2 # mount -o remount,rw /
sh-4.2 # passwd root (回车后需输入两次密码,成功后出现如下提示):
passwd:all authentication tokens updated successfully.

3. 加载 SELinux 策略,并重启系统

sh-4.2 # touch /.autorelabel
sh-4.2 # exec /sbin/init

系统初始化完毕后会自动重启,用新密码登录即可。

CentOS 7 修改内核启动顺序

1. 查看当前 grub2 的启动项:

cat /boot/grub2/grub.cfg

menuentry 后面的就是启动项。

例如改为 ‘CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)’

2. 一条命令:

grub2-set-default 'CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)'

例如

grub2-set-default 'CentOS Linux (3.10.0-327.36.3.el7.x86_64) 7 (Core)'

3. 验证一下是否有用:

grub2-editenv list

将会返回:

saved_entry=CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)

4. 重启即可。

docker环境搭建ELK

ELK是开源日志界的三大剑客,本文主要讲怎么在docker里头跑起来这一套东东。

镜像

这里采用docker-elk的镜像。

运行

cd docker-elk
eval "$(docker-machine env default)"
docker-compose up -d
...
Successfully built 68f1e0777077
Creating dockerelk_kibana_1
Attaching to dockerelk_elasticsearch_1, dockerelk_logstash_1, dockerelk_kibana_1
kibana_1        | Stalling for Elasticsearch
kibana_1        | Starting Kibana
elasticsearch_1 | [2016-02-03 12:01:46,067][INFO ][node                     ] [Caretaker] version[2.2.0], pid[1], build[8ff36d1/2016-01-27T13:32:39Z]
elasticsearch_1 | [2016-02-03 12:01:46,068][INFO ][node                     ] [Caretaker] initializing ...
elasticsearch_1 | [2016-02-03 12:01:46,615][INFO ][plugins                  ] [Caretaker] modules [lang-expression, lang-groovy], plugins [], sites []
elasticsearch_1 | [2016-02-03 12:01:46,635][INFO ][env                      ] [Caretaker] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [14gb], net total_space [18.1gb], spins? [possibly], types [ext4]
elasticsearch_1 | [2016-02-03 12:01:46,635][INFO ][env                      ] [Caretaker] heap size [1015.6mb], compressed ordinary object pointers [true]
elasticsearch_1 | [2016-02-03 12:01:49,038][INFO ][node                     ] [Caretaker] initialized
elasticsearch_1 | [2016-02-03 12:01:49,040][INFO ][node                     ] [Caretaker] starting ...
elasticsearch_1 | [2016-02-03 12:01:49,120][INFO ][transport                ] [Caretaker] publish_address {172.17.0.6:9300}, bound_addresses {[::]:9300}
elasticsearch_1 | [2016-02-03 12:01:49,130][INFO ][discovery                ] [Caretaker] elasticsearch/jOBlX_T5TYmgeE6jHP-z0Q
elasticsearch_1 | [2016-02-03 12:01:52,207][INFO ][cluster.service          ] [Caretaker] new_master {Caretaker}{jOBlX_T5TYmgeE6jHP-z0Q}{172.17.0.6}{172.17.0.6:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
elasticsearch_1 | [2016-02-03 12:01:52,250][INFO ][http                     ] [Caretaker] publish_address {172.17.0.6:9200}, bound_addresses {[::]:9200}
elasticsearch_1 | [2016-02-03 12:01:52,251][INFO ][node                     ] [Caretaker] started
elasticsearch_1 | [2016-02-03 12:01:52,259][INFO ][gateway                  ] [Caretaker] recovered [0] indices into cluster_state
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["warning","config"],"pid":1,"key":"bundled_plugin_ids","val":["plugins/dashboard/index","plugins/discover/index","plugins/doc/index","plugins/kibana/index","plugins/markdown_vis/index","plugins/metric_vis/index","plugins/settings/index","plugins/table_vis/index","plugins/vis_types/index","plugins/visualize/index"],"message":"Settings for "bundled_plugin_ids" were not applied, check for spelling errors and ensure the plugin is loaded."}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:sense","info"],"pid":1,"name":"plugin:sense","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:kibana","info"],"pid":1,"name":"plugin:kibana","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:elasticsearch","info"],"pid":1,"name":"plugin:elasticsearch","state":"yellow","message":"Status changed from uninitialized to yellow - Waiting for Elasticsearch","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:kbn_vislib_vis_types","info"],"pid":1,"name":"plugin:kbn_vislib_vis_types","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:markdown_vis","info"],"pid":1,"name":"plugin:markdown_vis","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:metric_vis","info"],"pid":1,"name":"plugin:metric_vis","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:spyModes","info"],"pid":1,"name":"plugin:spyModes","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:statusPage","info"],"pid":1,"name":"plugin:statusPage","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:table_vis","info"],"pid":1,"name":"plugin:table_vis","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["listening","info"],"pid":1,"message":"Server running at http://0.0.0.0:5601"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:49+00:00","tags":["status","plugin:elasticsearch","info"],"pid":1,"name":"plugin:elasticsearch","state":"yellow","message":"Status changed from yellow to yellow - No existing Kibana index found","prevState":"yellow","prevMsg":"Waiting for Elasticsearch"}
elasticsearch_1 | [2016-02-03 13:21:50,104][INFO ][cluster.metadata         ] [Caretaker] [.kibana] creating index, cause [api], templates [], shards [1]/[1], mappings [config]
elasticsearch_1 | [2016-02-03 13:21:50,489][INFO ][cluster.routing.allocation] [Caretaker] Cluster health status changed from [RED] to [YELLOW] (reason: [shards started [[.kibana][0]] ...]).
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:53+00:00","tags":["status","plugin:elasticsearch","info"],"pid":1,"name":"plugin:elasticsearch","state":"green","message":"Status changed from yellow to green - Kibana index ready","prevState":"yellow","prevMsg":"No existing Kibana index found"}

查看kibana

http://192.168.99.100:5601/
未分类

查看sense

http://192.168.99.100:5601/app/sense
未分类

默认端口

  • 5000: Logstash TCP input.

  • 9200: Elasticsearch HTTP

  • 9300: Elasticsearch TCP transport

  • 5601: Kibana

docker搭建rabbitmq集群

本文主要讲述如何用docker搭建rabbitmq的集群。

下载镜像

采用bijukunjummen该镜像。

git clone https://github.com/bijukunjummen/docker-rabbitmq-cluster.git

运行

启动集群

cd docker-rabbitmq-cluster/cluster
docker-compose up -d
......
Status: Downloaded newer image for bijukunjummen/rabbitmq-server:latest
docker.io/bijukunjummen/rabbitmq-server: this image was pulled from a legacy registry.  Important: This registry version will not be supported in future versions of docker.
Creating cluster_rabbit1_1
Creating cluster_rabbit2_1
Creating cluster_rabbit3_1

默认启动了三个节点

rabbit1:
  image: bijukunjummen/rabbitmq-server
  hostname: rabbit1
  ports:
    - "5672:5672"
    - "15672:15672"

rabbit2:
  image: bijukunjummen/rabbitmq-server
  hostname: rabbit2
  links:
    - rabbit1
  environment:
   - CLUSTERED=true
   - CLUSTER_WITH=rabbit1
   - RAM_NODE=true
  ports:
      - "5673:5672"
      - "15673:15672"

rabbit3:
  image: bijukunjummen/rabbitmq-server
  hostname: rabbit3
  links:
    - rabbit1
    - rabbit2
  environment:
   - CLUSTERED=true
   - CLUSTER_WITH=rabbit1
  ports:
        - "5674:5672"

查看

docker@default:~$ docker ps
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                                                                                  NAMES
ba5f665bb213        bijukunjummen/rabbitmq-server   "/bin/sh -c /opt/rabb"   10 minutes ago      Up 10 minutes       4369/tcp, 9100-9105/tcp, 15672/tcp, 25672/tcp, 0.0.0.0:5674->5672/tcp                  cluster_rabbit3_1
b9466e206b2b        bijukunjummen/rabbitmq-server   "/bin/sh -c /opt/rabb"   10 minutes ago      Up 10 minutes       4369/tcp, 9100-9105/tcp, 25672/tcp, 0.0.0.0:5673->5672/tcp, 0.0.0.0:15673->15672/tcp   cluster_rabbit2_1
b733201aeadf        bijukunjummen/rabbitmq-server   "/bin/sh -c /opt/rabb"   10 minutes ago      Up 10 minutes       4369/tcp, 0.0.0.0:5672->5672/tcp, 9100-9105/tcp, 0.0.0.0:15672->15672/tcp, 25672/tcp   cluster_rabbit1_1
88196436c434        daocloud.io/daocloud/daomonit   "/usr/local/bin/daomo"   37 hours ago        Up 2 hours                                                                                                 daomonit

访问:

http://192.168.99.100:15672,弹出登陆界面

未分类

输入guest/guest

未分类

docker环境搭建elasticsearch

本文主要讲如何使用使用docker搭建elasticsearch。

下载镜像

这里利用hangxin1940搭好的镜像,不过是es的1.4.2版本。

docker pull hangxin1940/docker-elasticsearch-cn:v1.6.0

启动容器

docker run -d -p 9200:9200 -p 9300:9300 --name es hangxin1940/docker-elasticsearch-cn:v1.6.0

查看es(这里的ip是docker的default machine的ip)

访问http://192.168.99.100:9200/

{
status: 200,
name: "node1",
cluster_name: "cn-out-of-box",
version: {
number: "1.6.0",
build_hash: "cdd3ac4dde4f69524ec0a14de3828cb95bbb86d0",
build_timestamp: "2015-06-09T13:36:34Z",
build_snapshot: false,
lucene_version: "4.10.4"
},
tagline: "You Know, for Search"
}

查看集群状态

http://192.168.99.100:9200/_plugin/head/

未分类

也可以用命令行

curl -XGET http://192.168.99.100:9200/_cluster/health?pretty

返回

{
  "cluster_name" : "cn-out-of-box",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 1,
  "active_shards" : 1,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 1,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0
}

这里目前只是单节点的,后续弄成集群看看。

查看插件

http://192.168.99.100:9200/_plugin/oob

未分类

增删改查

增加

curl -XPUT 'http://192.168.99.100:9200/twitter/tweet/1' -d '{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elastic Search"
}'

返回

{"_index":"twitter","_type":"tweet","_id":"1","_version":1,"created":true}%

查询

curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1'

返回

{"_index":"twitter","_type":"tweet","_id":"1","_version":1,"found":true,"_source":{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elastic Search"
}}%

未分类

高级查询:选择字段

curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1?fields=message,user&pretty=true'

返回

{
  "_index" : "twitter",
  "_type" : "tweet",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "fields" : {
    "message" : [ "trying out Elastic Search" ],
    "user" : [ "kimchy" ]
  }
}

高级查询:选择格式

curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1?fields=message,user&format=yaml'

返回

---
_index: "twitter"
_type: "tweet"
_id: "1"
_version: 1
found: true
fields:
  message:
  - "trying out Elastic Search"
  user:
  - "kimchy"

更新

curl -X PUT http://192.168.99.100:9200/twitter/tweet/1 -d '{"message": "hello world", "user": "patterncat"}'

返回

{"_index":"twitter","_type":"tweet","_id":"1","_version":2,"created":false}%

这个是覆盖更新,不是局部更新:

 ~  curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1'
{"_index":"twitter","_type":"tweet","_id":"1","_version":2,"found":true,"_source":{"message": "hello world", "user": "patterncat"}}%

删除

curl -XDELETE 'http://192.168.99.100:9200/twitter/tweet/1'

返回

{"found":true,"_index":"twitter","_type":"tweet","_id":"1","_version":3}%

查看mapping

{
    "twitter": {
        "mappings": {
            "tweet": {
                "properties": {
                    "message": {
                        "type": "string"
                    }, 
                    "post_date": {
                        "type": "date", 
                        "format": "dateOptionalTime"
                    }, 
                    "user": {
                        "type": "string"
                    }
                }
            }
        }
    }
}

索引分析

http://192.168.99.100:9200/twitter/_analyze?field=message&text=hello%20world

{
    "tokens": [
        {
            "token": "hello", 
            "start_offset": 0, 
            "end_offset": 5, 
            "type": "<ALPHANUM>", 
            "position": 1
        }, 
        {
            "token": "world", 
            "start_offset": 6, 
            "end_offset": 11, 
            "type": "<ALPHANUM>", 
            "position": 2
        }
    ]
}

docker搭建redis集群

这里参照了Docker 搭建redis 集群这篇文章来,非常顺利。

下载镜像

docker pull redis

准备配置文件

mkdir /home/docker/redis/  
wget https://raw.githubusercontent.com/antirez/redis/3.0/redis.conf -O /home/docker/redis/redis.conf
cd /home/docker/redis/  
sed -i 's/# slaveof <masterip> <masterport>/slaveof redis-master 6379/g' redis.conf  

启动redis容器

docker run --name redis-master -p 6379:6379 -d redis
docker run --link redis-master:redis-master -v /home/docker/redis/redis.conf:/usr/local/etc/redis/redis.conf --name redis-slave1 -d redis redis-server /usr/local/etc/redis/redis.conf
docker run --link redis-master:redis-master -v /home/docker/redis/redis.conf:/usr/local/etc/redis/redis.conf --name redis-slave2 -d redis redis-server /usr/local/etc/redis/redis.conf
docker run --link redis-master:redis-master -v /home/docker/redis/redis.conf:/usr/local/etc/redis/redis.conf --name redis-slave3 -d redis redis-server /usr/local/etc/redis/redis.conf 

查看redis集群

redis-cli 
127.0.0.1:6379> info
# Server
redis_version:3.0.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:48bba53ba79f07ac
redis_mode:standalone
os:Linux 3.13.0-27-generic x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.9.2
process_id:1
run_id:6d552d47e50137b6ee40697d7254891aa5dbdb68
tcp_port:6379
uptime_in_seconds:21554
uptime_in_days:0
hz:10
lru_clock:10637013
config_file:

# Clients
connected_clients:1
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:1926248
used_memory_human:1.84M
used_memory_rss:4419584
used_memory_peak:1963096
used_memory_peak_human:1.87M
used_memory_lua:36864
mem_fragmentation_ratio:2.29
mem_allocator:jemalloc-3.6.0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1453456066
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

# Stats
total_connections_received:5
total_commands_processed:64476
instantaneous_ops_per_sec:3
total_net_input_bytes:2426080
total_net_output_bytes:92455
instantaneous_input_kbps:0.14
instantaneous_output_kbps:0.02
rejected_connections:0
sync_full:3
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:222
migrate_cached_sockets:0

# Replication
role:master
connected_slaves:3
slave0:ip=172.17.0.2,port=6379,state=online,offset=30087,lag=1
slave1:ip=172.17.0.3,port=6379,state=online,offset=30101,lag=0
slave2:ip=172.17.0.4,port=6379,state=online,offset=30087,lag=1
master_repl_offset:30101
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:30100

# CPU
used_cpu_sys:7.37
used_cpu_user:5.34
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Cluster
cluster_enabled:0

# Keyspace