分类 linux 下的文章

用shell脚本反查搜索引擎蜘蛛IP

网上能搜到很多引擎蜘蛛的地址,这些地址不全而且好多已经过期了。如果想自己搜集蜘蛛的IP,最好的方法是分析网站的日志,即快又准确,但是不够全。如果有时间和资源,可以用本文的笨方法来抓取所有蜘蛛IP。原理是大多数的搜索引擎蜘蛛的ip都做了IP反解析,可以在linux下用host或者nslookup命令反查,先看几个例子

  1. 谷歌蜘蛛

    [root@nixops.me ~]# host 66.249.79.161
    161.79.249.66.in-addr.arpa domain name pointer crawl-66-249-79-161.googlebot.com.

  2. 百度蜘蛛

    [root@nixops.me ~]# host 220.181.108.170
    170.108.181.220.in-addr.arpa domain name pointer baiduspider-220-181-108-170.crawl.baidu.com.

  3. 搜狗蜘蛛

    [root@nixops.me ~]# host 106.120.173.147
    147.173.120.106.in-addr.arpa domain name pointer sogouspider-106-120-173-147.crawl.sogou.com.

  4. msn/bing

    [root@FreeBSD ~]# host 40.77.167.134
    134.167.77.40.in-addr.arpa domain name pointer msnbot-40-77-167-134.search.msn.com.

  5. yandex

    [root@FreeBSD ~]# host 141.8.142.56
    56.142.8.141.in-addr.arpa domain name pointer spider-141-8-142-56.yandex.com.

  6. yahoo

    [root@FreeBSD ~]# host 68.180.229.117
    117.229.180.68.in-addr.arpa domain name pointer b115329.yse.yahoo.net.
    以上这些搜索引擎蜘蛛IP都可以反查,也有部分搜索引擎是不支持反查的,如: YisouSpider和360,但360有提供蜘蛛IP地址,知道原理了,就可以写shell脚本来反查了,不多说直接上脚本

    #!/usr/bin/env bash

    # google dns, opendns,Comodo Secure DNS,level 3 dns,Verisign dns, 114 dns , alidns,baidu dns,dnspod dns,cnnic dns
    dns=(8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 8.26.56.26 8.20.247.20 4.2.2.1 4.2.2.2 64.6.64.6 64.6.65.6 114.114.114.114 114.114.115.115 223.5.5.5 223.6.6.6 180.76.76.76 119.29.29.29 182.254.116.116 1.2.4.8 210.2.4.8)
    result=/root/spider.txt

    function rand(){
    # min=$1
    # max=$(($2-$min+1))
    # num=$(cat /dev/urandom | head -n 10 | cksum | awk -F ' ' '{print $1}')
    # echo $(($num%$max+$min))
    expr $RANDOM % 19 + 1 # 共19台dns,产生1-19随机数
    }

    function cmd(){
    # rnd=$(rand 0 18)

     rnd=$(rand)
     dns=${dns[$rnd]} 
     timeout 1 host $1 $dns 

    }

    tmp_fifofile="/tmp/$$.fifo"
    mkfifo $tmp_fifofile # 新建fifo
    exec 6<>$tmp_fifofile # 将fifo文件的输入输出重定向到文件描述符6
    rm $tmp_fifofile

    thread=80 # 定义开启的线程数
    for ((i=0;i<$thread;i++));do

     echo

    done >&6 # 向fd6中写入$thread个空行

    for ((a=1;a<254;a++))
    do
    for ((b=0;b<254;b++))

        do
       for ((c=0;c<254;c++))
            do
           for ((d=1;d<254;d++))
             do
             read -u6  #从文件描述符6读取空行
              {
              cmd $a.$b.$c.$d |grep -i -E 'baidu|google|msn|yahoo|sogou|yandex|bot|spider' >> $result
               echo >&6  #补充用掉的回车符,保持线程数
                  } &       #每读取一个空行,将程序放入后台执行
             done
         done
         echo >&6    #每跑完一个C段在补充一次,防止因产生僵尸进程导致线程越来越少
     done

    done

    wait # 等待所有的后台子进程结束
    exec 6>&- # 关闭fd6
    exit 0

整个IPv4的地址实在太多了,如果单线程执行可能几年都执行不完,我这里开启了80个线程,跑完一个A段也大概要5天,如果机器配置够高可以在多开一些线程,能快一些,本脚本有几个缺点:

  1. bash只能用这种方法间接实现多线程,容易产生僵尸进程
  2. 虽然用多台dns轮询还是效率太低,查询太慢
  3. 网络占用比较小,但占用CPU资源比较高

综上,这个脚本玩玩就行了,如果真想反查还是用其它语言写吧

nginx动态添加访问白名单

本文实现的功能是:网站启用访问白名单,对于不在白名单中又需要访问的客户,只需打开一个不公开的网址,然后自动获得2小时的访问权限,时间达到后自动删除访问权限

实现此功能需要以下几个步骤:

  1. nginx启用访问白名单
  2. 客户打开指定网址自动添加访问白名单
  3. 为网址添加简单的认证
  4. 每两个小时自动恢复默认白名单,删除临时IP访问权限

一、nginx配置访问白名单

这个就比较简单了,简单贴一下配置:

............nginx.conf...........
geo $remote_addr $ip_whitelist {
default 0;
include ip_white.conf;
}
............server段............
location / {
        if ($ip_whitelist = 1) {
            break;
        }
       return 403;
    }

启用白名单的IP写在ip_white.conf文件中,格式为: 8.8.8.8 1;,只需将IP按照格式写入ip_white.conf中即可获得访问权限。详细配置方法:nginx启用IP白名单

二、使用LUA自动添加白名单

nginx需配合lua模块才能实现这个功能,新建一个location,客户访问这个location时,使用lua拿到客户IP并调用shell脚本写入ip_white.conf中,写入后自动reload nginx使配置生效,lua代码:

location /addip {
content_by_lua '

CLIENT_IP = ngx.req.get_headers()["X_real_ip"]
if CLIENT_IP == nil then
    CLIENT_IP = ngx.req.get_headers()["X_Forwarded_For"]
end
if CLIENT_IP == nil then
    CLIENT_IP  = ngx.var.remote_addr
end
if CLIENT_IP == nil then
    CLIENT_IP  = "unknown"
end
    ngx.header.content_type = "text/html;charset=UTF-8";
    ngx.say("你的IP : "..CLIENT_IP.."<br/>");
    os.execute("/opt/ngx_add.sh "..CLIENT_IP.."")
    ngx.say("添加白名单完成,有效时间最长为2小时");
';
}

/opt/ngx_add.sh shell脚本内容:

#!/bin/bash
ngx_conf=/usr/local/nginx/conf/nixops.me/ip_white.conf
ngx_back=/usr/local/nginx/conf/nixops.me/ip_white.conf.default
result=`cat $ngx_conf |grep $1`

case $1 in

rec)
    rm -rf $ngx_conf 
    cp $ngx_back $ngx_conf
     /usr/local/nginx/sbin/nginx -s reload
 ;;

*)
    if [ -z "$result" ]
       then
         echo  "#####add by web #####" >>$ngx_conf
         echo "$1 1;" >> $ngx_conf
         /usr/local/nginx/sbin/nginx -s reload
     else
         exit 0
     fi
;;
esac

该脚本有两个功能:

  1. 自动加IP并reload nginx
  2. 恢复默认的ip_white.conf文件,配合定时任务可以取消非默认IP的访问权限

nginx主进程使用root运行,shell脚本reload nginx需设置粘滞位:

chown root.root  /usr/local/nginx/sbin/nginx
chmod 4755 /usr/local/nginx/sbin/nginx

nginx启用lua模块见nginx启用lua模块

三、添加简单的认证

使用base auth 添加简单的用户名密码认证,防止非授权访问,生成密码文件:

printf "nixops.me:$(openssl passwd -crypt 123456)\n" >>/usr/local/nginx/conf/pass

账号:nixops.me
密码:123456

在刚刚的location中加入:

location /addip {

            auth_basic "nginx auto addIP  for nixops.me";
            auth_basic_user_file /usr/local/nginx/conf/pass; 
            autoindex on;
......Lua代码略......

四、自动恢复默认IP白名单

通过web获得访问权限的IP,设置访问有效期为两小时,我是通过每两小时恢复一次默认的IP白名单文件实现。把ip_white.conf文件复制一份作为默认的白名单模版:

 cp /usr/local/nginx/conf/nixops.me/ip_white.conf /usr/local/nginx/conf/nixops.me/ip_white.conf.default

使用定时任务每两小时通用上面的shell脚本来恢复,定时任务为:

1 */2 *  *  * root /opt/ngx_add.sh rec

使用ssl加密Nginx与uptream servers之间的流量

nginx做为一款优秀的反向代理软件,最常见的架构是:

客户 <---> NGINX(反向代理) <---> 后端服务器(upstream servers)

如果nginx和后端服务器都在公网上,按常规配置,nginx与后端服务器之间的流量是明文传输的,很容易受到篡改、嗅探或者被GFW认证。我就遇到了NGINX反代后端服务器时,竟然被劫持了!!!
Nginx作为工作在7层的软件,最常用的加密方式就是https了,我只需要加密nginx到upstream servers之间的流量,不需要浏览器认证,所以自签名证书就够了,此作法需要:

1. 自签名证书
2. 后端服务器配置https
3. nginx配置解密私钥

一、生成自签名证书
使用openssl生成签名证书:

openssl  req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout nixops.me.key -out nixops.me.crt

二、后端服务器配置自签名证书
为了不影响后端的https配置,我启用了一个新端口,配置自签名证书。我后端(upstream servers)也是nginx服务器

server {
    listen     12345;

    ssl on;
    ssl_certificate        "/etc/ssl/certs/nixops.me.crt";
    ssl_certificate_key    "/etc/ssl/certs/nixops.me.key";

    ...... server configs ......

}

三、NGINX配置upstream加密
nginx(反向代理)配置upstream和解密私钥:

upstream backend {
    server backend1.nixops.me:12345;
    server 8.8.8.8:12345;
    check interval=3000 rise=2 fall=3 timeout=30000 type=tcp;
    #check interval=3000 rise=2 fall=3 timeout=30000 type=http;
    #check_http_send "GET / HTTP/1.0\r\nConnection: keep-alive\r\nHost:www.nixops.me\r\n\r\n";
    #check_http_expect_alive http_2xx http_3xx;

   }

server {
    listen     80;

    ssl_certificate_key    "/etc/ssl/certs/nixops.me.key";
    
    location / {
        proxy_redirect         off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass https://backend;
    }
}

配置好后,nginx到后端的upstream servers就会使用https加密了。
我的NIGNX版本tengine 2.1.2(nginx 1.6.1),nginx版本非常低。如果使用的是官方nginx,版本在1.9.2以上,有另外的模块可以实现Upstream加密的功能,原理是一样的。可以参考官方文章:https://www.nginx.com/resources/admin-guide/nginx-tcp-ssl-upstreams/

使用saltstack初始化系统

目前工作中使用最多的还是Fabric,最近把所有服务器都装上了saltstack,但是目前并没有使用saltstack进行管理,用的最多的还是进行系统和环境的初始化。主要是因为其它同事对saltstack不够熟悉,还有就是生产上的模块和环境都比较复杂,想完全使用saltstack管理还要一个循序渐进的过程,自动化运维想要用还是要趁早建设,越晚束手束脚的地方越多

一、saltstack安装

2.1 简介

saltstack是比较流行的开源配置管理工具,主要特点有:

  1. 基于Python开发,轻量级、灵活、扩展性好
  2. 使用ZeroMQ,确保速度和可靠性
  3. C/S架构,加密通讯,可管理海量客户端,并行能力强
  4. 配置简单、容易学习和使用

主要功能:

  1. 配置管理,自动配置系统和软件环境的状态
  2. 批量命令执行

saltstack软件组件,以下是官方文档中的介绍:

  1. salt-master: 主控制端(Server端),也叫Master
  2. salt-minion: 被控制端(client端),也叫Minion
  3. salt-ssh : 无Minion模式,使用ssh管理客户端,类似ansible
  4. salt-syndic :任务分发的代理,向Minion端发放任务
  5. Execution Modules:执行模块,在Minion系统上执行命令
  6. Runners :即使用salt-run,在Master端执行的命令
  7. Formulas (States):配置管理,描述Minion系统的目标状态
  8. Grains :在minion启动时收集到的系统静态信息
  9. Pillar :在Master端上定义的变量,供满足条件的Minion使用,通常是敏感信息
  10. Reactor : 基于事件触相应的操作
  11. Top File :入口文件
  12. Returners :将Minion执行结果发送给第三方系统

2.2 安装

我是centos系统,直接yum安装,epel源里也有,但是比官方的老一点,推荐使用官方源安装

yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest-1.el6.noarch.rpm

安装并启动Master:

yum install salt-master
service salt-master start

启动salt-master后,zeromq会监听两个端口:

  • 4505:发布消息
  • 4506:接受消息

安装Minion:

yum install salt-minion

启动Minion端之前需在配置文件中指定Master的IP,支持IP和域名:

sed -i 's/#master: salt/master: master.nixops.me/' /etc/salt/minion

启动Minion:


service salt-minion start

2.3 认证

master和minion通信之间使用AES加密。minion启动后,会生成公钥和私钥,并将公钥发送给master,被master接受后,master就能对minion发送指令了。同时Master在启动后也会生产公钥和私钥,minion端也会保留master的公钥
Master端查看key状态:

salt-key -L

服务端接受Minion的公钥:

salt-key -a salt-client

执行测试命令:


salt '*'  test.ping

有返回就说明正常通信了,可以用Master管理Minion端了

二、使用saltstack进行配置管理

saltstack的配置管理通过编写sls文件实现,sls文件描述了目标系统的状态,编写sls文件之前,需先在Master端设置保存sls文件的file_roots和pillar_roots,编辑/etc/salt/master,按需添加如下内容:

file_roots:
      base:
        - /etc/salt/base
      prod:
        - /etc/salt/prod

pillar_roots:
      base:
        - /etc/salt/pillar/base
      prod:
        - /etc/salt/pillar/prod

saltstack的sls文件使用YAML定义数据,top.sls文件为states的入口文件

top.sls
base:
    '*':
    - init.*

看一下目录结构:

tree /etc/salt/base
├── init
│   ├── cron.sls
│   ├── date_time.sls
│   ├── dirmode.sls
│   ├── dns.sls
│   ├── files
│   │   ├── limits.conf
│   │   └── resolv.conf
│   ├── history.sls
│   ├── pkg.sls
│   ├── selinux.sls
│   ├── sysctl.sls
│   └── ulimits.sls
└── top.sls

安装并更新常用的软件:pkg.sls

#install epel yum source
epel-release:
    pkg.installed:
        - refresh: True
#install or keep the base packages  latest
init_pkgs:
    pkg.latest:
        - pkgs:
            - yum
            - telnet
            - lrzsz
            - iptables
            - ntpdate
            - crontabs
            - policycoreutils   #selinux modules for saltstack
            - policycoreutils-python

更改时区并校准时间:date_time.sls

include:
      - init.pkg
date_time_setting:
    timezone.system:
        - name: Asia/Shanghai
        - utc: True
cmd.run:
    - name: ntpdate time.windows.com
    - require:
        - init_pkgs

定时任务管理: cron.sls

ntp_cron:
    cron.present:
        - name: ntpdate pool.ntp.org >/dev/null
        - user: root
        - hour: 4

配置系统DNS:dns.sls

/etc/resolv.conf:
    file.managed:
        - source: salt://init/files/resolv.conf
        - user: root
        - group: root
        - mode: 644

更改生产目录权限:dirmode.sls

/web:
file.directory:
    - name: /web
    - user: root
    - group: root
    - dir_mode: 755
    - file_mode: 644
    - recurse:
        - user
        - group
        - mode

记录所有用户bash历史命令到/var/log/bash_history.log:history.sls

/etc/profile:
file.append:
    - text: |
        function log2syslog
        {
        export HISTTIMEFORMAT="[%Y-%m-%d %H:%M:%S] [`who am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`]"
        export PROMPT_COMMAND='\
          if [ -z "$OLD_PWD" ];then
                export OLD_PWD=$(pwd);
          fi;
        if [ ! -z "$LAST_CMD" ] && [ "$(history 1)" != "$LAST_CMD" ]; then
            echo  `whoami`_shell_cmd "[$OLD_PWD]$(history 1)" >>/var/log/bash_history.log;
        fi ;
        export LAST_CMD="$(history 1)";
        export OLD_PWD=$(pwd);'
        }
        trap log2syslog DEBUG
    - unless: grep log2syslog /etc/profile

env_source:
    cmd.run:
        - name: source /etc/profile
        - unless: env |grep  HISTTIMEFORMAT
        - require:
            - file: /etc/profile

关闭selinux:selinux.sls

permissive:
selinux.mode
disabled_selinux:
    file.replace:
        - name: /etc/sysconfig/selinux
        - pattern: SELINUX=enforcing
        - repl: SELINUX=disabled

更改系统最大能打开的文件数:ulimits.sls

/etc/security/limits.conf:
file.managed:
    - source: salt://init/files/limits.conf
    - user: root
    - group: root
    - mode: 644

cmd.run:
    - name: ulimit -a
    - unless:  grep 65535 /etc/security/limits.conf

设置内核参数:sysctl.sls

#本地tcp可使用端口范围
net.ipv4.ip_local_port_range:
    sysctl.present:
        - value: 10000 65000
#设置可以打开的最大文件数
fs.file-max:
    sysctl.present:
        - value: 2000000
#减少swap分区使用
vm.swappiness:
    sysctl.present:
        - value: 0

salt也有一些预先写好的Formulas(Formulas are pre-written Salt States),想省事可以直接拿来用,地址: https://github.com/saltstack-formulas

参考文章:

http://lixcto.blog.51cto.com/4834175/d-1

linux下配置和安装KVM虚拟机

最近要在外网搞一套监控系统,正好有一台服务器配置比较高,也没跑什么重要的业务,就拿来划了一个KVM虚拟机,可能是平时各种虚拟机用的比较多,配置起来感觉比想象中简单的多,简单记录下过程

准备工作

宿主机为centos 6.8 64位,检查宿主机CPU是否支持虚拟化:

cat /proc/cpuinfo | egrep '(vmx|svm)' | wc -l;

结果大于0表示支持

安装kvm

KVM核心软件包:

yum install kvm libvirt python-virtinst qemu-kvm virt-viewer bridge-utils

如果服务器上有桌面环境,想使用图形界面管理器virt-manager,可以安装完整的KVM环境:

yum groupinstall Virtualization 'Virtualization Client' 'Virtualization Platform' 'Virtualization Tools'

验证内核模块是否加载:

lsmod | grep kvm

启动虚拟机管理接口服务:

/etc/init.d/libvirtd start

设置开机启动:

chkconfig libvirtd on

启动libvirtd后,会自动创建了一个网卡,并启动dnsmasq服务,用来为虚拟机分配IP地址

创建虚拟机

下载虚拟机要安装的ISO系统镜像文件,之后需创建存储池,指定在宿主机上虚拟机磁盘的存储位置,创建存储目录:


mkdir -p /opt/kvm

定义一个储存池和绑定目录:

virsh pool-define-as vmspool --type dir --target /opt/kvm

建立并激活存储池:

virsh pool-build vmspool
virsh pool-start vmspool

使用存储池创建虚拟机,并通过vnc连接:

virt-install \
--hvm    \ #全虚拟化
--name=zabbix  \#虚拟机名字
--ram=4096   \ #分配内存
--vcpus=4     \  #分配CPU数
--cdrom=/opt/kvm/iso/CentOS-7-x86_64-DVD-1511.iso \ #使用的ISO
--virt-type=kvm \ #虚拟机类型
--disk  path=/opt/kvm/zabbix.qcow2,device=disk,format=qcow2,bus=virtio,cache=writeback,size=100 \ #磁盘大小,格式
--network netwrok=default \  #网络设置,defalut为NAT模式
--accelerate \  #KVM内核加速
--graphics vnc,listen=0.0.0.0,port=5922,password=123123\ #vnc配置
--force \
--autostart

之后使用vnc客户端连接 宿主机IP:5922,即可使用图形安装系统;也可以选择nographics模式,无需vnc在命令行下安装,建议使用vnc
安装完成后会生成:

  1. 虚拟机的配置文件:/etc/libvirt/qemu/zabbix.xml
  2. 虚拟硬盘文件:/opt/kvm/zabbix.qcow2
  3. NAT网络配置文件:/etc/libvirt/qemu/networks/default.xml

配置网络

KVM可以配置两种:

  1. NAT网络: 虚拟机使用宿主机的网络访问公网,宿主机和虚拟机能互相访问,但不支持外部访问虚拟机
  2. 桥接网络: 虚拟机复用宿主机物理网卡,虚拟机与宿主机在网络中角色完全相同,支持外部访问

配置NAT网络

默认会有一个叫default的NAT虚拟网络,查看NAT网络:

virsh net-list --all

如果要创建或者修改NAT网络,要先编辑default.xml:

virsh  net-edit default

重新加载和激活配置:

virsh  net-define /etc/libvirt/qemu/networks/default.xml

启动NAT网络:

virsh net-start default
virsh net-autostart default

启动NAT后会自动生成一个虚拟桥接设备virbr0,并分配IP地址,查看状态:

brctl show

正常情况下libirtd启动后就会启动virbr0,并自动添加IPtables规则来实现NAT,要保证打开ip_forward,在/etc/sysctl.conf中:

net.ipv4.ip_forward = 1
sysctl -p

启动虚机并设置自动获取IP即可,如果想手动指定虚拟机IP,要注意配置的IP需在NAT网段内

配置桥接网络

系统如果安装了桌面环境,网络会由NetworkManager进行管理,NetworkManager不支持桥接,需要关闭NetworkManger:

chkconfig NetworkManager off
chkconfig network on
service NetworkManager stop
service network start

不想关闭NetworkManager,也可以在ifcfg-br0中手动添加参数"NM_CONTROLLED=no"
创建网桥:

virsh iface-bridge eth0 br0

创建完后ifconfig会看到br0网桥,如果eth0上有多个IP,更改下相应的文件名,如:ifcfg-eth0:1改为ifcfg-br0:1
编辑虚拟机的配置文件,使用新的网桥:

virsh edit zabbix

找到网卡配置,改为:

<interface type='bridge'>
  <mac address='52:54:00:7a:f4:9b'/>
  <source bridge='br0'/>
  <model type='virtio'/>
  <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>

我是用的br0,为虚拟机添加多块网卡只需复制多个interface,并确保mac address和PCI地址不同即可
重新加载配置:

virsh define /etc/libvirt/qemu/zabbix.xml

重启虚拟机:

virsh shutdown zabbix
virsh start zabbix

之后使用VNC连接虚拟机并设置下网络即可

常用操作

KVM相关操作都通过vish命令完成,参数虽然多,但是功能一目了然,很直观

创建虚拟机快照:

virsh  snapshot-create-as --domain zabbix --name init_snap_1

也可以简写成:

virsh  snapshot-create-as  zabbix  init_snap_1

快照创建后配置文件在/var/lib/libvirt/qemu/snapshot/zabbix/init_snap_1.xml
查看快照:


snapshot-list zabbix

删除快照:

 snapshot-delete zabbix  init_snap_1



排错

  1. ERROR Format cannot be specified for unmanaged storage.
    virt-manager 没有找到存储池,创建储存池即可
  2. KVM VNC客户端连接闪退
    使用real vnc或者其它vnc客户端连接kvm闪退,把客户端设置中的ColourLevel值设置为rgb222或full即可
  3. virsh shutdown 无法关闭虚拟机
    使用该命令关闭虚拟机时,KVM是向虚拟机发送一个ACPI的指令,需要虚拟机安装acpid服务:
    yum -y install acpid && /etc/init.d/acpid start
    否则只能使用virsh destroy 强制关闭虚拟机

参考文章

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization_Host_Configuration_and_Guest_Installation_Guide/index.html

asterisk双向回拨功能实现

目前我们公司电话系统经过两年的发展,已经实现了两个异地办公室、上百部分机,三个机房节点,多家voip供应商的之间的互通与网络冗余,算的上一个小型的呼叫中心了,一直比较懒写这方面的文章。最近公司正好有做回拨的需求,随便写篇关于这方面的文章。
需求:客户通过网站前台提交电话号码,电话系统先呼叫指定客服分机或响铃组,客服摘机后系统呼叫客户电话号码,客户接听后开始与客服通话。

我们的电话系统用的是freePBX,系统自带回拨功能(callback)功能比较简单,商业模块(WebCallBack)可以实现web提交号码,但这两个模块都只能先呼叫客户,客户接通后才能呼叫客服,无法自定义呼叫顺序,不满足我们的需求,只能自己开发了。好在asterisk支持自动呼叫脚本(.call files),功能实现起来比较容易,先看一下脚本工作流程:

1. asterisk 启动时需加载pbx_spool.so 模块支持自动呼叫脚本,Freepbx是自动加载的
2. 按需求编写呼叫脚本,保存为扩展名为.call的文件
3. 将.call脚本移到到/var/spool/asterisk/outgoing/目录下
4. 系统检测到该脚本并自动执行呼叫流程

呼叫脚本语法:

发起呼叫的参数:
Channel: <channel>: 呼叫的通道,可以是分机,trunk,响铃组等等
CallerID: "name" <number>  主叫id,即显示的号码和名称
MaxRetries: <number> 呼叫失败后重试次数,不包括原始呼叫
RetryTime: <number>  等待多久重新尝试呼叫
WaitTime: <number>  等待接听超时的时间
Account: 使用的Accoud code,CDR计费方面会用到

呼叫接通后的参数:
Context: <context-name> 使用的拨号方案
Extension: <ext>  拨号方案的目标号码
Priority: <priority> 优先级
Set: 设置变量
Application: 要启动的应用
Data: 应用使用的数据参数
AlwaysDelete: Yes/No 更改时间为将来时,不会删除该文件
Archive: Yes/No  使否将执行过的脚本归档到outgoing_done

来写一个hello world脚本:

channel: SIP/801   ;我的分机号
Callerid: "call" <801>
Application: Playback
Data: hello-world

将脚本保存为helloworld.call,手动复制到/var/spool/asterisk/outgoing/,系统就会拨打分机801,播放hello world后挂机。
我的freepbx对接了很多的voip供应商,freepbx会生产默认拨号方案:outbound-allroutes,根据用户拨号自动选择呼出线路,如我的规则:使用呼出线路1来打10086的拨号为:1 86 75510086。下面在写一个呼叫脚本:

channel: SIP/801   ;分机
Callerid: "回拨" <801>
Context: outbound-allroutes
Extension: 18675510086
    MaxRetries: 0
    RetryTime: 0 ;加上这两条,否则5分钟后会重拨

这个脚本个功能是先呼叫分机801,在分机801接听后,系统开始呼叫10086,10086接听后801就可以与10086通话了。
这个脚本中分机801接听后,系统大概需要5秒才能接通10086,之间没有任何提示,freepbx的系统自带了一些提示,编写一个拨号方案加入提示,编辑:etc/asterisk/extensions_custom.conf,加入:

[saylast4num]
exten = _XX.,1,NoOp(say last 4 number of client number works) 
exten = _XX.,n,Wait(1)
exten = _XX.,n,Playback(calling)   ;系统提示音 calling
exten = _XX.,n,SayDigits(${EXTEN:-4}) ;读拨打号码的后4位
exten = _XX.,n,Goto(autocall_out,${EXTEN},1) ;跳转到自动呼出的拨号方案
[autocall_out]
include => outbound-allroutes

修改上面的呼叫脚本为:

channel: SIP/801   ;分机
;channel: Local/400@from-internal  ;本地响铃组400
Callerid: "回拨" <801>
Context: saylast4num
Extension: 18675510086

执行一下,801分机接听后系统会提示“calling 0086”,然后呼叫075510086,以这个脚本为模版,将18675510086替换为客户的号码,在用python封装成web api,就可以实现从web接收号码,写相应call脚本到/var/spool/asterisk/outgoing/,实现我们所需的回拨功能,python +flask写几十行代码就可以搞定

其实不使用呼叫脚本,使用originate也能实现,一个简单的shell脚本:

#!/bin/bash
asterisk -x "channel originate SIP/$1 extension $2@outbound-allroutes"

保存为call.sh ,用法: call.sh 801 18675510086
先呼叫客户在接通内部分机的情况,最方便的是直接花50刀买webcallback模块,这个我不多说了

参考文章:

http://www.voip-info.org/wiki/view/Asterisk+auto-dial+out

openvpn的搭建与使用

openvpn多数人用来科学上网,能保证安全性与速度,同时配置和稳定性也非常好。我在生产环境中也使用了很久,但比较懒一直都没有整理文档,这次正好有两台服务器之间要做加密连接,简单整理了一下

一、安装

下载:


wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.11.tar.gz

依赖包:

yum install gcc gcc-c++ make  -y
yum install lzo lzo-devel -y
yum install pam pam-devel -y
yum install openssl openssl-devel -y

编译和安装:

./configure --prefix=/usr/local/openvpn
make && make install

epel源里有openvpn,也可以用yum 安装:


yum install -y epel-release
yum install openvpn easy-rsa

二、SSL证书生成

easy-rsa是openvpn生成服务端证书的脚本,自openvpn 2.3开始easy-rsa已经独立出来,下载:

git clone https://github.com/OpenVPN/easy-rsa
cd easy-rsa/easyrsa3/

初始化生成证书所需的信息,按实际情况修改:

cp vars.example vars

取消并修改以下选项:

set_var EASYRSA_REQ_COUNTRY     "CN"
set_var EASYRSA_REQ_PROVINCE    "Hongkong"
set_var EASYRSA_REQ_CITY        "Hongkong"
set_var EASYRSA_REQ_ORG         "NIXOPS.ME"
set_var EASYRSA_REQ_EMAIL       "admin@nixops.me"
set_var EASYRSA_REQ_OU          "Nixops Openvpn"

其它参数可以默认,也可以按需修改

初始化并创建ca根证书:

./easyrsa init-pki
./easyrsa build-ca

一路回车即可,ca证书需要输入密码,这个密码是给服务器端和客户端签名时用的
创建并签名服务器端证书:

./easyrsa gen-req server-ssl nopass
./easyrsa sign server server-ssl

同样一路回车即可
创建Diffie-Hellman证书,该证书主要作用是确保共享KEY安全穿越不安全网络:

./easyrsa gen-dh

创建并签名客户端证书:

./easyrsa gen-req client-ssl nopass
./easyrsa sign client client-ssl

所有证书文件:

[root@nixops.me easyrsa3]# tree pki
pki
├── ca.crt    -->ca证书, server/client 都需要
├── certs_by_serial
│   ├── 01.pem
│   └── 02.pem
├── dh.pem    -->Diffie-Hellman证书,server端需要
├── index.txt
├── index.txt.attr
├── index.txt.attr.old
├── index.txt.old
├── issued
│   ├── client-ssl.crt    --> 客户端证书
│   └── server-ssl.crt    --> 服务器端证书
├── private
│   ├── ca.key
│   ├── client-ssl.key    --> 客户端私钥
│   └── server-ssl.key    --> 服务器端私钥
├── reqs
│   ├── client-ssl.req
│   └── server-ssl.req
├── serial
└── serial.old

三、配置openvpn服务器端和客户端

3.1 服务器端配置

openvpn的源码目录中已经有配置模版了,复制模版:

[root@nixops.me openvpn-2.3.11]# cp   sample/sample-config-files/server.conf  /etc/openvpn/

复制证书文件:

[root@nixops.me easyrsa3]# cp pki/ca.crt pki/issued/server-ssl.crt pki/private/server-ssl.key /etc/openvpn/

贴一份服务器端配置:

#openvpn监听本地ip地址,可选
;local a.b.c.d
#监听tcp或udp端口,如果有多个服务端,要设置不同的端口
port 1194
#tcp模式还是udp模式
proto tcp
#虚拟网络接口类型:1. TUN :路由模式,工作在三层,无物理地址,效率高;无法与物理网卡桥接,会无视广播包,客户端可以是TUN/TAP
#2. TAP :桥接模式,工作在二层,有物理地址,效率不如TUN;可以与物理网卡桥接,广播包可以通过,客户端必须是TAP
dev tun
#证书配置
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server-ssl.crt
key /etc/openvpn/server-ssl.key
dh /etc/openvpn/dh.pem
#客户端使用的网段
server 10.8.0.0 255.255.255.0
#维持客户和ip的对应关系,重连后能保持虚拟ip
ifconfig-pool-persist ipp.txt
#为客户端推送路由,允许客户端访问其它网段
;push "route 192.168.10.0 255.255.255.0"
#设置所有客户端默认网关为VPN,所有流量经过vpn
;push "redirect-gateway def1 bypass-dhcp"
#为客户端推送DNS
;push "dhcp-option DNS 208.67.222.222"
#允许客户端之间互相访问
client-to-client
#允许多个客户端使用相同证书连接
duplicate-cn
#存活检测,每10秒检测一次,120秒未响应则认为连接丢失
keepalive 10 120
#对数据进行压缩,server和client 需保持一致
comp-lzo
#最大客户端数量
;max-clients 100
#重新连接时,不重新读取key和保持tun/tap设备在线
persist-key
persist-tun
#记录openvpn状态信息
status openvpn-status.log
#记录并追加日志
;log         openvpn.log
;log-append  openvpn.log
#日志级别
verb 5

前台启动,检查配置是否正确:

/usr/local/openvpn/sbin/openvpn --config /etc/openvpn/server.conf

如果启动没有错误,即可以daemon后台运行server:

/usr/local/openvpn/sbin/openvpn --daemon --config /etc/openvpn/server.conf

开启路由转发:

sed -i '/net.ipv4.ip_forward/s/0/1/' /etc/sysctl.conf
sysctl -p

防火墙策略配置:

允许vpn客户端所在网段流量转发到其它网卡:

iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT

将vpn客户端的流量转到eth0,允许vpn客户端上网,即NAT:

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j  MASQUERADE

还需根据vpn服务器端的工作模式放开tcp/udp的1194端口,这个规则就不写了

3.2 客户端配置

客户端各系统下都有现成包,配置是通用的,我这里还是在linux下使用openvpn的客户端。

复制一份样板:

cp sample/sample-config-files/client.conf /etc/openvpn/

直接贴一份配置:

client
dev tun
proto tcp
remote openvpn.nixops.me  1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client-ssl.crt
key /etc/openvpn/client-ssl.key
remote-cert-tls server
comp-lzo
verb 3

多个vpn client在不同的内网时,可以在client.conf中根据client的网段push路由,会比在server.conf中指定更方便
测试启动:

/usr/local/sbin/openvpn --config /etc/openvpn/client.conf 

启动:

/usr/local/sbin/openvpn --daemon --config /etc/openvpn/client.conf --log /var/log/openvpn.log

总的来说配置还是比较简单的

linux的cpu和磁盘io优先级设置

在服务器上常常会运行一些备份脚本,当备份的文件比较多时,会占用大量的cpu和磁盘io。为了不影响生产业务,应尽量减少这些脚本运行时使用的cpu和磁盘io。通常linux下限制cpu使用有三种方法:

  1. nice/renice : 调整进程使用cpu的优先级
  2. cpulimit :不修改进程的nice值,通过暂停进程一段时间,来限制cpu使用
  3. cgroups :内核提供的机制,可以限制、记录、隔离一组进程所使用的cpu、内存、磁盘、网络等资源,是docker等容器的基础技术之一

限制磁盘io :

  1. ionice : 调整io调度的优先级
  2. cgroups

这里只说nice和ionice,实际上nice和ionice只是改变优先级,并没有真正的限制

一、nice

1.1 进程优先级

要理解nice值,首先要说明一下优先级的概念,先来看一下进程的信息:

[root@nixops.me ~]# ps -efl
F S UID         PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
5 S asterisk  5319  1607  -5  80   0 - 119325 ep_pol Mar23 ?       00:03:55 /usr/sbin/httpd
  • PRI 指进程优先级,优先级小的进程会获得比较多的CPU时间,程序就会被优先处理
  • NI 即为nice值
  • 两者关系为 :PRI(new)=PRI(default)+nice

其中nice值可以用户指定,nice的默认值为0,root可用范围从-20到19,普通用户只能用0到19,值越小PRI(new)越小,CPU执行优先级越高。同时可以知道:只有root能提高优先级,普通用户只能降低优先级。

1.2 设置程序启动时的优先级

nice 只有一个参数 : -n,启动程序时指定优先级:

nice -n -20  /opt/backup.sh  #优先级最高
nice -n 19  /opt/backup.sh   #优先级最低

1.3 设置程序运行时的优先级

对于已经在运行的程序,如果需要调整优先级,需要用renice命令,设置正在运行程序nice的值为15:

[root@nixops.me ~]# renice -n +15 5319 

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
5 S asterisk  5319  1607  -5  95  15  - 119325 ep_pol Mar23 ?       00:03:55 /usr/sbin/httpd

root用户可以为其它用户或组设置nice值:

[root@nixops.me ~]# renice -n +15 -u zabbix   #设置zabbix用户的所有进程nice值为15
[root@nixops.me ~]# renice -n +15 -u zabbix   #设置zabbix用户的所有进程nice值为15

还可以为进程组设置nice值,查看进程组:


[root@nixops.me ~]# ps -efj 
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
asterisk  5296  1607  1607  1607  0 Mar23 ?        00:03:54 /usr/sbin/httpd
asterisk  5319  1607  1607  1607  0 Mar23 ?        00:03:55 /usr/sbin/httpd
asterisk  5394  1607  1607  1607  0 Mar23 ?        00:03:55 /usr/sbin/httpd

apache的进程组(PGID)为:1607,设置nice值为-8:

[root@nixops.me ~]# renice  -n -8 -g 1607

二、ionice

linux默认IO调度器使用CFQ调度算法,支持用ionice命令为程序指定io调度策略和优先级,IO调度策略分为三种:

  • Idle :其他进程没有磁盘IO时,才进行磁盘IO
  • Best Effort:缺省调度策略,可以设置0-7的优先级,数值越小优先级越高,同优先级的进程采用round-robin算法调度;
  • Real Time :立即访问磁盘,无视其它进程IO
  • None 即Best Effort,进程未指定策略和优先级时显示为none,会使用依据cpu nice设置计算出优先级

策略 :0 - none, 1 - Real Time, 2 - Best Effort, 3 - idle

使用idle策略:

ionice -c 3 -p 进程id

使用Real Time策略:

ionice -c 1  -p 进程id

使用Best Effort策略,并指定优先级最低:

ionice -c 2 -n 7 -p 进程id

三、同时限制cpu和磁盘io的优先级
为了对生产环境造成影响最小,设置备份脚本运行时,cpu和磁盘io的优先级都最低:

nice -n 19 ionice -c2 -n7  /bin/sh /opt/backup.sh

参考文章:
https://linux.cn/article-4742-1.html
http://www.linuxde.net/2013/06/13933.html

最新文章

最近回复

分类

归档

统计

  • 文章总数:168篇
  • 分类总数:5个
  • 评论总数:103条
  • 页面总数:172个
  • 本站运行:4885天

其它