iptables配置只允许PHP 9000端口访问

以一键安装包搭建的环境为基础,php 默认是监听在 127.0.0.1:9000 。本文以此为例进行配置说明:

通常,设置 iptables 会对于服务器的对外访问都设置为允许比如:

filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0]

允许 9000 端口入站规则就可以 ,配置示例如下:

服务器安全

如果出站规则设置的比较严格,设置默认 OUTPUT 为 DROP,则需补充设置对应的规则:

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

服务器安全

备注:默认情况下,CentOS 下 iptables 的配置文件在 /etc/sysconfig/iptables,修改配置文件之后需要重启 iptables 生效。

Linux桌面系统iptables安全配置

服务器安全

Linux 的安全声誉一直比 Windows 系统要好,但它也并不完美。有许多 Linux 发行版都没有采用最佳的安全默认值,所以用户在安装好系统之后,大多需要自行实施安全配置。

例如:Linux 桌面安装完成后,默认的防火墙配置都不像 Windows 那样已经内置了很多常用的安全策略,而需要用户手动进行安全配置。

而不论是 Linux 桌面版还是服务器版本,都内置了 iptables 这一包过滤器(严格来说只是包过滤器的控制器),在本指南中,系统极客将向大家介绍如何使用 iptables 来保护您的 Linux 桌面系统安全。

什么是iptables

iptables 是内置于 Linux 内核中的包过滤器,几乎所有 Linux 发行版都自带了此功能。它是控制计算机进、出网络流量的最直接方式,在很多场景下都被当作防火墙来使用。

iptables 在开源领域、Linux 行业或普通用户中都有不小的名声,你不需要了解 iptables 的繁杂内容就可以在 Linux 桌面上有效地使用它,但还是需要掌握一些基本知识才能用好。

iptables命令结构

所有 iptables 规则都遵循相同的基本结构。简单来说,每条规则其实都是可以单独执行的 iptables 命令,它会告诉 Linux 内核如何处理特定端口的流量。 示例如下:

-A INPUT -i eth0 -p tcp -m state --state ESTABLISHED,RELATED --sport 80 -j ACCEPT

上述命令看似复杂,但我们将其拆开来看的话,其实真的很简单。首先,这条规则的 -A 表示将此条规则附加到你的 iptables 规则上。

随后的 -i 标志指定了此规则所用的网络接口 eth0。(你在编写自己的规则时,请确保知道通过哪个网口连接到网络。)

-p 标志用于指定协议,以上这条规则适用于 tcp 协议。

-m 标志有点不同,它用于判断必须满足的条件才能使流量不被拒绝。 此规则的条件是状态。

–sport 代表「源端口」,它告诉 iptables 流量来自哪个端口。 还有一个 –dport 标志代表「目标端口」,它用于处理哪些端口流量可到达 OUTPUT。

最后还有 -j 标志,它用于对符合此条 iptables 规则的数据包执行 ACCEPT、DROP 或 REJECT 操作。

对于普通用户来说,最常见的 iptables 命令参数就是如此,普通桌面 Linux 用户应该够用了。但如果你想要详细并全面了解 iptables,还需要把表(tables)、链(chain)、规则(rules)以及 iptables 的数据包处理流程都研究清楚才行,在这里我们不做详细说明。

使用iptables规则文件

所有 Linux 用户在配置 iptables 策略时都可以逐条输入命令,但每次都单独配置的话会非常繁琐,而且不利于复用。所以,创建单独的 iptables 规则文件就要明智得多。

iptables 规则文件只要是文本文件类型即可,而且必需以如下格式开头和结尾。本文我们使用 /tmp/iptables-ip4 文件作为示例,在文件中添加以下两行,所有规则都被包在它们之间。

*filter
#规则
#规则
#规则
COMMIT

适用于Linux桌面安全的iptables规则

回到本文的主题,现在开始介绍用于保护 Linux 桌面安全的常见 iptables 规则。当然,如下规则只是对普通 Linux 桌面环境的安全建议,如果你还在运行其他服务或需要打开其他端口,也可以调整某些内容或添加自己的规则。

Loopback

环回接口是 Linux 使用的内部接口:

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

Ping

有许多用户都喜欢对自己的桌面计算机禁 Ping,但系统极客建议大家尽量不要对桌面系统禁 Ping,这对于日常的网络连接测试还是很有用的。如果要允许 ping,请添加下面的规则:

-A INPUT -i ens33 -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT
-A INPUT -i ens33 -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -o ens33 -p icmp -j ACCEPT

Web访问

大家日常办公的机器显然是需要访问网页的,所以可用如下规则打开 Web 服务访问:

-A INPUT -i ens33 -p tcp -m state --state ESTABLISHED,RELATED --sport 80 -j ACCEPT
-A INPUT -i ens33 -p tcp -m state --state ESTABLISHED,RELATED --sport 443 -j ACCEPT

-A OUTPUT -o ens33 -p tcp -m tcp --dport 80 -j ACCEPT
-A OUTPUT -o ens33 -p tcp -m tcp --dport 443 -j ACCEPT

当然,要将网站的域名解析为 IP 地址还需要允许 DNS 查询:

-A INPUT -i ens3 -s 192.168.1.1 -p udp --sport 53 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -o ens3 -d 192.168.1.1 -p udp --dport 53 -m udp -j ACCEPT

时间服务

大多数 Linux 桌面会使用 NTP 服务来设置和维护来自 Internet 的系统时间。 所以,需要允许你的计算机连接到 NTP 服务器以获取时间:

-A INPUT -i ens33 -p udp -m state --state ESTABLISHED,RELATED --dport 123 -j ACCEPT
-A OUTPUT -o ens33 -p udp -m udp --sport 123 -j ACCEPT

打印服务

除非你使用的是 USB 打印机或其它方式连接的外部打印机,不然还需要启用与 CUPS 的网络连接:

-A INPUT -p udp -m udp --dport 631 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 631 -j ACCEPT
-A OUTPUT -p udp -m udp --sport 631 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 631 -j ACCEPT

电子邮件

对于电子邮件的发送和接收可能会比较棘手,在这里我们允许的是使用 SSL 协议的电子邮件端口:

# IMAP
-A INPUT -i ens33 -p tcp -m state --state ESTABLISHED,RELATED --sport 993 -j ACCEPT
-A OUTPUT -o ens33 -p tcp -m tcp --dport 993 -j ACCEPT

# POP3
-A INPUT -i ens33 -p tcp -m state --state ESTABLISHED,RELATED --sport 995 -j ACCEPT
-A OUTPUT -o ens33 -p tcp -m tcp --dport 995 -j ACCEPT

# SMTP
-A INPUT -i ens33 -p tcp -m state --state ESTABLISHED,RELATED --sport 465 -j ACCEPT
-A OUTPUT -o ens33 -p tcp -m tcp --dport 465 -j ACCEPT

如果你还需要使用不安全的电子邮件,请替换这些端口。

SSH服务

为了使用 SSH 连接还需要允许 SSH 数据包的流入和流出:

# Input
-A INPUT -i ens3 -p tcp -m state --state NEW,ESTABLISHED --dport 22 -j ACCEPT
-A OUTPUT -o ens3 -p tcp -m state --state ESTABLISHED --sport 22 -j ACCEPT
# Output
-A OUTPUT -o ens3 -p tcp -m state --state NEW,ESTABLISHED --dport 22 -j ACCEPT
-A INPUT -i ens3 -p tcp -m state --state ESTABLISHED --sport 22 -j ACCEPT

DHCP服务

大多数 Linux 桌面都通过 DHCP 服务自动从路由器(或 DHCP Server)获取 IP 地址。 DHCP 服务使用自己专有的端口,所以也需要允许其数据包通行。

-A INPUT -i ens33 -p udp -m state --state ESTABLISHED,RELATED --sport 67:68 -j ACCEPT
-A OUTPUT -o ens33 -p udp -m udp --dport 67:68 -j ACCEPT

如果你使用静态 IP,则不需要这些规则。

拒绝其它数据包

日常需要用到的端口和协议都开放了,最后就需要告诉 iptables 绝对拒绝上面规则中没有明确允许的数据包内容:

-A INPUT -j REJECT
-A FORWARD -j REJECT
-A OUTPUT -j REJECT

一切准备妥当之后,你的 iptables 规则文件看起来应该像这样:

服务器安全

导入iptables规则

现在,你已经有了适用于自己环境 Linux 桌面安全的 iptables 规则,只需将它交给 iptables 来使用即可。不过,如果你此前已经添加了一些规则,可以通过如下命令将其清除:

sudo iptables -F && sudo iptables -X

服务器安全

清理完成后,使用如下命令导入 iptables 规则文件:

sudo iptables-restore < /tmp/itpables-ip4

如果要查看当前计算机正使用的新 iptables 规则,可以通过如下命令查看:

sudo iptables -S

服务器安全

最后还需要提醒大家注意,通过手动或规则文件添加的 iptables 规则都不是永久的。如果你重启计算机,这些规则都将被清空,需要重新添加或从文件导入。

配置iptables永久规则

要让 iptables 规则永久化的方法很多,而且不同 Linux 发行版的配置方式也不尽相同。出于 Debian 和 Ubuntu 系统最受广大 Linux 桌面用户的欢迎,所以以其作为示例。

在 Debian 和 Ubuntu 中有一款被称为 iptables-persistant 的应用可以在重启系统的过程中保存和恢复 iptables 规则,所以需要先安装:

sudo apt install iptables-persistent

服务器安全

在安装过程中,软件包会询问您是否要永久保存 iptables 配置,选择「是」就行。

将来在变更了 iptables 规则时,可以运行以下命令再次永久保存:

sudo service netfilter-persistent save

修复CentOS7的MBR和GRUB

一:修复MBR:

MBR(Master Boot Record 主引导记录) 硬盘的0柱面、0磁头、1扇区称为主引导扇区。其中446Byte是BootLoader,64Byte为Partition table,剩下的2Byte为magic number

1:查看一下前512个字节的内容

系统管理

2:破坏bootloader(这里的block size 只要小于等于446即可)

系统管理

3:再查看一下前512个字节,分区表未破坏

系统管理

4:重启之后在光盘引导界面选择Troubleshotting

系统管理

5:进入救援模式

系统管理

6:此时挂载光盘加载了一个Linux系统

系统管理

7:根据提示输入1之后进入救援模式的命令行

系统管理

8:使用 grub2-install 命令重建BootLoader

系统管理
显示无错误,使用sync写入磁盘

9:现在看一下是否修复

系统管理

10:恢复成功,重启一下试试,grub正常运行

系统管理
至此,MBR修复完成

二:修复GRUB

1:看下grub2目录下的存放的文件

系统管理

2:直接删除grub2目录后重启

rm -rf /boot/grub2/
reboot

3:重启之后进入了 grub rescue> 模式,但是不能识别命令,所以还是要进入救援模式

系统管理

4:进入救援模式后切根

chroot /mnt/sysimage/

5:使用 grub2-install 命令修复grub

系统管理

6:现在查看一下是否修复

系统管理

7:修复grub配置文件

系统管理

8:此时/boot/grub2/下已生成grub.cfg文件。退出并重启看系统是否能正常启动

系统管理
启动成功,grub2修复完成

docker运行golang应用

搭建 mysql 环境

mysql.app

docker run --net=host -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=letchat -d  hub.c.163.com/library/mysql:latest

1. 通过容器编译并运行当前目录下的 golang程序(依赖需要先下载到当前目录 vendor中)

gobuild.app

docker run --net=bridge --rm -v $PWD:/go/src/app -w /go/src/app hub.c.163.com/library/golang:latest  go build -v

2. 使用 Docker构建镜像,在此镜像上运行一个容器,使用该容器运行 golang程序

Dockerfile

FROM hub.c.163.com/library/golang:latest

WORKDIR /go/src/app
COPY . .

#RUN go-wrapper download   # "go get -d -v ./..."
RUN go-wrapper install    # "go install -v ./..."

CMD ["sh","-c","/go/bin/app"]

gorun.app

# build image  app
docker build -t app:latest .

# set env
export GIN_MODE=release

# make the container
docker run --net=host -it -d app:latest

2 种方式选1个。第一个是直接在本地生成一个 app 程序,可以直接 ./app 运行。第二个是在容器内部运行 app程序,但是网络端口使用宿主机的端口,相当于直接在本机上运行。

docker部署node应用

环境:centos7

docker的安装以及一些设置

安装docker

     yum install docker

启动docker服务

     systemctl start docker.service

设置开机启动

     systemctl enable docker.service

pull下nodejs镜像

说是docker hub 慢,就找到了一个国内的镜像去下载

     docker pull hub.c.163.com/nce2/nodejs:0.12.2

未分类

查看镜像

     docker images

未分类

创建node应用

然后在工作目录下创建package.json文件

     vi package.json

写入内容
未分类

创建server.js,也就是我们node应用的主文件

     vi server.js

写点内容
未分类

创建Dockerfile文件

在项目代码更目录创建Dockerfile文件

     vi Dockerfile

写入以下内容
未分类
下面简单解释下Dockerfile文件

FROM hub.c.163.com/nce2/nodejs:0.12.2

FROM是构建镜像的基础镜像源,后面的一串是我们刚才pull下来的那个Image,如果本地没有Docker,会自己pull镜像的。

#Create app directory
RUN mkdir -p /home/Service
WORKDIR /home/Service

第一句RUN用于在Image里创建一个文件夹,将会用于保存我们的代码。
第二句WORKDIR是将我们创建的文件夹作为工作目录。

# Bundle app Source
COPY . /home/Service
RUN npm install

第一句的COPY是把本机当前目录下的所有文件拷贝到Image的 /home/Service目录下。
第二句的RUN是用npm 安装我们的node应用中的所有依赖包。

EXPOSE 8888

我们的node应用监听的是8888端口,我们可以把这个端口暴露给主机。这样我们就可以从外网访问我们的应用了。

CMD ["npm" , "start"]

用来启动我们的node应用。

构建Image

在我们的Dockerfile所在的目录下执行构建命令

docker build -t mynodeapp .

别忘了最后那个点,不久我们会看到成功构建的信息。
未分类

然后我们去查看一下我们构建的镜像

docker images

未分类

运行构建的Image

docker run -d -p 8888:8888 50550c

-d表示容器会在后台运行,-p表示端口映射,把本机的8888端口映射到container的8888端口,这样外网就可以通过本机访问我们的应用,
后面的50550c是我们Image的ID,没写后面的是因为根据这几个就能定位出来了。

竟然报错了,也不能访问8888端口。想了一下,应该是镜像的问题。
就跑去dochub找了官方镜像,修改Dockerfile里的基础镜像

FROM node:4-onbuild

然后再次构建我们的应用

docker build -t nodeapp .

然后开始从官网下载镜像,确实特别慢..等了好久才下载完1个。貌似需要下载9个文件..
在漫长的等待过程中。。。
未分类

算了,放弃。。找找国内镜像试试吧~~

然后去daocloud注册了帐号,在这拉镜像吧

未分类
很快,镜像pull下来了。然后查看下现在的镜像。

未分类
现在我们去改下Dockerfile的基础镜像吧。

FROM daocloud.io/library/node

现在我们再来构建下镜像试试

docker build -t nodeapp .

看到了构建成功的信息,接着查看一下imges

然后启动:

docker run -d -p 8888:8888 7b784

果然出现了问题… 启动不成功,最后才知道,镜像和Dockerfile都是对应的,不对应就可能会出现上面的所有问题。(切记)

最近还是选择了官网的镜像,等待了40分钟左右,全部pull下来了,开始干活~~

修改Dockerfile文件如下:

FROM node:4-onbuild
# replace this with your application's default port
EXPOSE 8888

重新构建:

docker build -t my-node-apps .

未分类

启动docker镜像:

docker run -d -p 8888:8888 8b

然后查看下container

docker ps

未分类

然后用浏览器访问下8888端口:

未分类
完美!!!!!!!!!这次终于成功了~

然后去删除没用的images和container…

若要删除所有的image, 使用命令:

docker rmi  $( docker  images -q )

删除container

docker rm id

总结

因为镜像的事情走了不少弯路,浪费了很多的时间,所以最好还是去官网下需要的东西,然后看官方给的文档,英文的也要尽力去看。
今后还要去做学习一些images的管理,container的管理,以及应用日志处理相关的东西。

docker-compose快速搭建python开发环境

Docker提供了容器级别的资源隔离。由于Python的外部依赖管理中存在的问题,我们通常会使用virtualenv来对不同的项目创建其唯一的依赖环境。这时利用Docker进行Python开发,可以轻松解决不同Python项目之间的依赖隔离问题。

作为应用程序,我们通常需要依赖于多种外部服务,比如数据库、缓存服务等等。Docker-compose就是在Docker容器的基础上,提供了统一的容器编排语言,可以让你更轻松的利用Docker构建你的应用环境。

编写Dockerfile

我们使用requirements.txt定义我们的第三方python包依赖
Python
Project-Root
|– static
|– templates
|– server.py
|– requirements.txt
|– Dockerfile
|– docker-compose.yml

编写Dockerfile内容如下:
Python
在Dockerfile中,我们主要目的:通过requirements.txt文件安装第三方的Python库依赖;利用Docker的容器隔离,可以忽略掉很多在本地开发中需要使用的东西,比如virtualenv。

编排我们的Docker容器

在案例中,应用程序依赖了mongodb作为数据存储服务,以及redis作为缓存服务。在一般情况下,作为开发团队要么我们搭建统一的mongodb;要不就每个人在开发机上单独部署。

而在Docker中,我们则不在需要做这么多无用的事情。 Docker官方提供了大量的基础容器,基本涵盖了日常开发中我们需要的大部分依赖。 在https://hub.docker.com/我们可以搜索到我们需要的基础镜像。

比如mongodb以及redis,在docker-hub上官方都提供了容器话的服务。

以redis容器为例,我们在本地搭建redis服务要做的事情主要包括两步:
Python
这个时候我们就可以通过访问0.0.0.0:63775来访问我们的redis服务器了。

我们也可以通过Docker原生的命令来连接我们的应用容器和redis容器,以使我们的代码能够正常的访问redis服务
Python
而事实上,我们可以使用更加简化的方式来定义我们的容器组合管理,使用Docker-compose(前身Fig)来定义我们的容器组合关系。
Python
这里我们定义了3个容器web、redis、mongo。 其中,web容器是通过当前目录的Dockerfile进行构建,同时将当前目录挂在到/app目录。 而redis和mongo则直接使用官方进行。

通过使用links,我们可以在web容器中通过 ‘redis:6375’以及’mongo:21707’直接访问相应的服务。

开始Coding吧

Python
Docker会根据当前的目录下得Dockerfile构建基础镜像,并且使用python server.py运行程序,并且运行redis以及mongo服务。

同时由于使用了volumes挂载了本地目录到/app,此时如果我们是开启的Debug模式,我们就可以直接在本地使用你喜欢的文本编辑器去编写代码,并且更新的代码能够实时被重新加载。

当然在使用Docker中最漫长的过程就是,下镜像,下镜像&下镜像。
Python

RedHat6.5安装配置Cacti监控工具

Cacti 在英文中的意思是仙人掌的意思,Cacti是一套基于PHP、MySQL、SNMP及RRDTool开发的网络流量监测图形分析工具。它通过snmpget来获取数据,使用 RRDtool绘画图形,它的界面非常漂亮,能让你根本无需明白rrdtool的参数能轻易的绘出漂亮的图形。而且你完全可以不需要了解RRDtool复杂的参数。它提供了非常强大的数据和用户管理功能,可以指定每一个用户能查看树状结 构、host以及任何一张图,还可以与LDAP结合进行用户验证,同时也能自己增加模板,让你添加自己的snmp_query和script!功能非常强大完善,界面友好。可以说,Cacti将rrdtool的所有“缺点”都补足了!

官方网站:http://www.cacti.net。好了,Cacti的简单介绍我们就说到这里了,下面我们来看一下Cacti的工作流程。

  • 主机环境 RedHat6.5 64位
  • 实验环境 服务端1 ip 172.25.25.1
    服务端2 ip 172.25.25.2
  • 安装包 cacti-0.8.8h.tar.gz
    php-snmp-5.3.3-26.el6.x86_64.rpm
    cacti-spine-0.8.8g.tar.gz
  • 防火墙状态:关闭
  • Selinux状态:Disabled

1.配置安装cacti及测试

A)配置安装cacti

[root@sever1 Asia]# yum install rrdtool mysql-server php httpdphp-mysql php-xml net-snmp net-snmp-utils- y                        #安装cacti之前要安装的包

[root@sever1 Asia]# cd /mnt/

[root@sever1 mnt]# ls

cacti-0.8.8h.tar.gz php-snmp-5.3.3-26.el6.x86_64.rpm

cacti-spine-0.8.8g.tar.gz

[root@sever1 mnt]# rpm -vih php-snmp-5.3.3-26.el6.x86_64.rpm

[root@sever1 mnt]# vim /etc/php.ini

946 date.timezone =Asia/Shanghai

[root@sever1 mnt]# tar zxf cacti-0.8.8h.tar.gz -C/var/www/html/  #解压到/var/www/html/目录

[root@sever1 mnt]# cd /var/www/html/

[root@sever1 html]# ls

cacti-0.8.8h

[root@sever1 html]# ln -s cacti-0.8.8h/ cacti          #作软链接

[root@sever1 html]# ls

cacti cacti-0.8.8h

[root@sever1 include]# /etc/init.d/mysqld start        #开启数据库

[root@sever1 include]# mysql_secure_installation

初始化,默认没密码,这里将密码设置成了redhat

[root@sever1 html]# cd cacti/                 

[root@sever1 cacti]# mysql -predhat -e "create databasecacti"      #创建名为cacti的数据库

[root@sever1 cacti]# mysql -predhat cacti < cacti.sql              #将cacti.sql文件导入到cacti数据库中

[root@sever1 cacti]# mysql -predhat -e "grant all oncacti.* to cacti@localhost identified by 'redhat'"                #创建本地cacti用户,并将cacti数据库的所有权限给cacti用户

[root@sever1 html]# cd include/               

[root@sever1 include]# vim config.php                  #修改配置文件
 29 $database_username ="cacti";                        #刚创建的cacti数据库的用户名

 30 $database_password ="redhat";                      #用户cacti的密码

 39 $url_path ="/cacti/";

 42 $cacti_session_name ="Cacti";
[root@sever1 cacti]# useradd -u 1000 cacti              #在系统中创建cacti用户

[root@sever1 cacti]# ll

total 1068

-rw-rw-r– 1 cacti cacti 5860 Feb 8 2016 about.php

-rw-rw-r– 1 cacti cacti 5348 Feb 8 2016 auth_changepassword.php

-rw-rw-r– 1 cacti cacti 14690 Mar 7 2016 auth_login.php

-rw-rw-r– 1 cacti cacti 178349 Apr 10 2012 cacti.sql

-rw-rw-r– 1 cacti cacti 20257 Feb 8 2016 cdef.php

[root@sever1 cacti]# su - cacti                        #切换到cacti用户

[cacti@sever1 ~]$ crontab -e                            #创建定时任务

*/5 * * * * php /var/www/html/cacti/poller.php > /dev/null2>&1

[cacti@sever1 ~]$ logout

[root@sever1 ~]# /etc/init.d/httpd start                #开启httpd

Stopping httpd: [ OK ]

安装cacti 172.25.25.1/cacti

点击next

监控
点击next
监控
在测试之前,时间得同步

B)测试 172.25.25.1/cacti

登陆 用户名:admin 密码:admin
监控
第一次登陆,会提示修改密码
监控
登陆之后,如图:
监控
点击graphs,如图:
监控

[root@sever1 cacti]# cd rra        #采集数据存放的位置

[root@sever1 rra]# ls

等待5分钟之后

[root@sever1 rra]# ls                  #已经有数据了

localhost_load_1min_5.rrd localhost_mem_swap_4.rrd localhost_users_6.rrd

localhost_mem_buffers_3.rrd localhost_proc_7.rrd

查看图像,如图:
监控

利用python探测谷歌搜索可用IP

原理是查询_netblocks.google.com域名的TXT记录,这个记录有大量网段的谷歌IP,再探测443端口开放的IP。不过探测出开放443端口的IP后,可能还要使用curl来检测是不是谷歌搜索的服务器。这一步需要与443端口ssl握手,但验证证书是否一致,使用python暂时写不出来,可以用curl https://www.google.com –resolve www.google.com:443:1.2.3.4,其中1.2.3.4为要探测的谷歌IP。
python脚本:

#!/usr/bin/python
# -*- coding:utf-8 -*-
'''
install modules:
pip install dnspython
'''

import dns.resolver
import struct, socket
import re
import sys
import threading
import Queue

threadLock = threading.Lock()
SHARE_Q = Queue.Queue()  
_WORKER_THREAD_NUM = 10
GLOBAL_COUNTER = 0

class MyThread(threading.Thread) :

    def __init__(self, func) :
        super(MyThread, self).__init__()
        self.func = func

    def run(self) :
        self.func()


def worker() :
    global SHARE_Q
    global GLOBAL_COUNTER
    while not SHARE_Q.empty():
        item = SHARE_Q.get()

        if check_port(item):
            with threadLock:
                print(item)
                GLOBAL_COUNTER += 1
                if GLOBAL_COUNTER >= 100:
                    sys.exit(0)

def get_txt_record(domain):
    answers = dns.resolver.query(domain, 'TXT')
    for rdata in answers:
        return str(rdata)


def get_ip_range_from_txt_record(txt_record):
    ip_range = []
    re_ret = re.findall(r'ip4:([^ ]+)', txt_record)
    for ip_mask in re_ret:
        ip_range.append(ip_mask)

    return ip_range

def get_ip_from_cidr(ip_range):
    ips = []
    for ip_mask in ip_range:
        (ip, cidr) = ip_mask.split('/')
        cidr = int(cidr) 
        host_bits = 32 - cidr
        i = struct.unpack('>I', socket.inet_aton(ip))[0] # note the endianness
        start = (i >> host_bits) << host_bits # clear the host bits
        end = i | ((1 << host_bits) - 1) 

        for i in range(start, end):
            ips.append(socket.inet_ntoa(struct.pack('>I',i)))

    return ips

def check_port(address, port=443):
    s=socket.socket()
    s.settimeout(1)  
    try:
        s.connect((address,port))
        return True
    except socket.error,e:
        return False

def main():
    txt_record = get_txt_record("_netblocks.google.com")
    ip_range = get_ip_range_from_txt_record(txt_record)
    ips = get_ip_from_cidr(ip_range)

    global SHARE_Q
    threads = []
    for task in ips :  
        SHARE_Q.put(task)

    for i in xrange(_WORKER_THREAD_NUM) :
        thread = MyThread(worker)
        thread.start()
        threads.append(thread)
    for thread in threads :
        thread.join()


if __name__ == '__main__':
    main()

shell脚本:


while read ip;do if curl -s -m 3 https://www.google.com.hk --resolve www.google.com.hk:443:$ip -o /dev/null;then echo $ip fi done < ip.txt

使用ps grep awk kill杀掉进程

程序成为僵尸进程以后需要通过进程号来强制终止,因此先需要获取进程的pid

 ps | grep test | awk 'NR==1{print $1}'  

获取test进程的ID,具体形式要按照linux输出的格式来,我的设备中的是第一行的第一列的第一个参数即为test的PID

由于通过管道把PID传给KILL -9无法生效。因此需要使用

ps | grep cwmpd | awk 'NR==1{print $1}' | xargs kill -9 

但是当前嵌入式设备上无法使用xargs 所以我们需要使用如下的方式:

 kill -9 `ps | grep test | awk 'NR==1{print $1}' `  # 注意这里是反单引号

或者:

 kill -9 $(ps | grep test | awk 'NR==1{print $1}') 

使用awk合并空行

[root@localhost ~]#cat urfile
[DEFAULT]
key1=value1
key2=value2
key3=value3


[agent]
key1=value1
key2=value2
key3=value3




[database]
key1=value1
key2=value2
key3=value3


[redis]
key1=value1
key2=value2
key3=value3

  

需求:
文本开头没有空行,section之间的空行行数不定,最后一个section之后也有n行空行,想将section之间的空行压缩成一行

解法一:
PF大神太绝了,直接一个cat -s urfile就搞定了;将多行空行合并成一行

解法二:
awk除去空行awk NF urfile
但没有做过将多行合并成一行,第一反应是用脚本
不过更喜欢awk一行流

[root@localhost ~]#awk -vRS="" '{print $0"n"}' urfile

  

开始对这个不是很理解,只是懂将行分隔符替换成空了

[root@localhost ~]#awk -vRS="" '{print NR $0"n"}' urfile
1[DEFAULT]
key1=value1
key2=value2
key3=value3

2[section1]
key1=value1
key2=value2
key3=value3

3[section2]
key1=value1
key2=value2
key3=value3

4[section3]
key1=value1
key2=value2
key3=value3
[root@localhost ~]#awk -vRS="" '{print $0"END"}' urfile
[DEFAULT]
key1=value1
key2=value2
key3=value3END
[section1]
key1=value1
key2=value2
key3=value3END
[section2]
key1=value1
key2=value2
key3=value3END
[section3]
key1=value1
key2=value2
key3=value3END

  

如果RS被设置为空,那么awk会将连续的空行作为行分隔符,与RS设置成”nn+”有什么区别???
1、忽略文件开头和结尾的空行。且文件不以记录分隔符结束,即最后不是空行,会将最后一个记录的尾n去掉
2、设置RT变量未空
3、影响FS变量
这个怎么理解?对于1、2两点,当作习题留给大家自己测试,3我们下节来讲。

总结下RS的3种情况:
1) 非空字符串
以固定字符串作为行分隔符,同时设置变量RT为固定字符串
2) 正则表达式
以正则表达式作为行分隔符,同时设置变量RT为正则表达式实际匹配到的字符串
3) 空字符
以连续的空行作为行分隔符,如果FS为单个字符,会将n强制加入到FS变量中

理解了RS,再来理解ORS就简单了。RS是awk读取文件时的行分隔符,ORS则是awk输出时的行结束符。
更简单的讲,就是awk在输出时,会在每行记录后面增加一个ORS变量所设定的值。
ORS的值只能设定为字符串,默认情况下,ORS的值是n