2020-04-03
再谈cuckoo与suricata

再谈cuckoo与suricata suricata到底可以做哪些工作?再谈cuckoo与suricatasuricata 与cuckoo可以有机的进行结合。suricata还原的文件可以给cuckoo使用,cuckoo中恶意文件产生的数据流量报文,可以反过来给suricata回放规则检测。二者可以有机进行...

Read More
 2020-04-03
docker学习记录


docker的网络模式

当你开始大规模使用Docker时,你会发现需要了解很多关于网络的知识。Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理。然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分。因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求。本文首先介绍了Docker自身的4种网络工作方式,然后介绍一些自定义网络模式。

安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host

模式 简介 备注
host模式 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口 优势:性能高,适用于对网络效率有较高要求,但是对于端口会于宿主机冲突
bridge模式 此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信 拥有独立隔离的网络
none模式 该模式关闭了容器的网络功能,挂在这个网络下的容器除了 lo,没有其他任何网卡 在保密闭环的空间中使用,一般不使用
Container模式 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。 两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
自定义网络模式 Docker 提供三种 user-defined 网络驱动:bridge, overlay 和 macvlan。overlay 和 macvlan 用于创建跨主机的网络 docker network create -d bridge –subnet 172.25.0.0/16 network_name

docker-host网络

11585881740_.pic_hd.jpg

docker-bridge网络

docker默认的网络连接方式为bridge,即桥接模式。在实际运行中会生成一个虚拟的网桥docker0,这边的虚拟网桥就类似于物理交换机的作用,而veth则可以类比物理交换机的端口 ,veth与容器内的eth0网卡 就是一队veth-pair,关于veth-pair技术可以参考该链接Linux-虚拟网络设备-veth pair,. 而docker0作为linux普通网桥,可以配置ip,这样便可以在三层进行网络通讯了。 20170828171704363.png

Docker 创建一个容器的时候,会执行如下操作:

  • 创建一对虚拟接口/网卡,也就是veth pair,分别放到本地主机和新容器中;
  • 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 vetha596da4;
  • 容器一端放到新容器中,并修改名字作为 eth0,这个网卡/接口只在容器的名字空间可见;
  • 从网桥可用地址段中(也就是与该bridge对应的network)获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 vetha596da4。
  • 完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。
  • 如果不指定–network,创建的容器默认都会挂到 docker0 上,使用本地主机上 docker0 接口的 IP 作为所有容器的默认网关。

iptables

ipforward

我们知道bridge模式下,会生成虚拟docker0,docker0为容器的默认网关。作为容器与外界通讯的媒介,docker0 与宿主机的网卡如何通讯呢? 这边其实就利用了linux多网卡数据包的转发功能。

Linux系统默认多网卡之间的数据包转发功能是关闭的。开启方法如下: 数据包转发功能默认配置 cat /proc/sys/net/ipv4/ip_forward 0 设置为1的时候转发 开机自动数据包转发 把下面代码添加到开机启动项/etc/rc.d/rc.local echo “1″ >/proc/sys/net/ipv4/ip_forward 或者修改/etc/sysctl.conf net.ipv4.ip_forward = 1

docker常见问题解答

Q:docker build的时候需要连接外网,但是有时候连接不上,为什么如何解决?

A: docker build 默认采用bridge模式,该方式需要桥接网卡,但是没看到。所以采用host 模式进行 docker build --network=host -t test . 参考:https://www.debugself.com/2018/01/17/docker_network/

附录

  1. docker容器的网络配置
  2. docker-compose配置ipv6

Read More
 2020-04-02
Python3实现Http中间件

背景介绍

项目需要编写一个中间件,对面提供Http接口,首先肯定想到的就是对 基于python3的简易http-server进行改造。 但是项目实际过程中,中间件的调用可能来自多方,多个用户都会对这个接口进行异步的调用,所以该接口就需要对异步的调用进行及时的处理。

ps: 直接运行的话可以 python3 -m http.server

框架选择

首先可以想到的是http-server框架与flask框架。

  • 首先联想到cuckoo-agent模块,agent.py。 他是基于python2的SimpleHTTPServer实现的。对其并发性能没有深入研究,不过该agent主要部署在虚拟机中,同时也只会处理一个任务。
  • http-server比较简单,而flask则是python实现web服务器的通用框架。不管http-server、flask都是一个轻量级别的服务。
  • 对于并发请求http-server,它可以有多个连接,但是同时只能处理一条请求任务。该方式就一定会产生阻塞。一开始想的是利用 超时函数,超过固定的秒数就直接返回,但是该方式在多用户的情况下,不是一个很好的选择。
  • 对于flask 实现http服务,很显然更快捷,但是你会发现一些问题,就是你同一条指令、同一浏览器重复请求,会出现阻塞情况。尽管使用了多线程。 可以参考该连接:python flask如何解决同时请求同一个请求的阻塞问题?。当然也有解决方法,不过先入为主了。

因此,问题就变为了,如何处理http-server的并发问题: 后来也找到了解决方式 就是使用ThreadingMixIn,参考python3 HttpServer 实现多线程

代码demo

http-server 基于flask demo


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 参考: https://www.cnblogs.com/liangqihui/p/9139270.html
from flask import Flask, abort, request, jsonify

app = Flask(__name__)

# 测试数据暂时存放
tasks = []

@app.route('/add_task/', methods=['POST'])
def add_task():
    if not request.json or 'id' not in request.json or 'info' not in request.json:
        abort(400)
    task = {
        'id': request.json['id'],
        'info': request.json['info']
    }
    tasks.append(task)
    return jsonify({'result': 'success'})


@app.route('/get_task/', methods=['GET'])
def get_task():
    if not request.args or 'id' not in request.args:
        # 没有指定id则返回全部
        return jsonify(tasks)
    else:
        task_id = request.args['id']
        task = filter(lambda t: t['id'] == int(task_id), tasks)
        return jsonify(task) if task else jsonify({'result': 'not found'})


if __name__ == "__main__":
    # 将host设置为0.0.0.0,则外网用户也可以访问到这个服务
    app.run(host="0.0.0.0", port=8383, debug=True)

http-server 基于http.server demo

这边用到了一个装饰器,用于判断函数运行超时,返回信息。

from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import subprocess
import os
import time
from threading import Timer
import getpass
import logging
import os.path
import sys
import signal
import codecs
# from signal import signal, SIGPIPE, SIG_DFL


sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())

data = {'result': 'this is a agent!!'}
# 监听主机 & 端口
host = ('0.0.0.0', 4322)
# gvm指令请求超时时间,单位秒
gvm_order_timeout = 6


class Node():
    def __init__(self):
        self.connect_method = ""  # 连接方法
        self.host_name = "127.0.0.1"  # 主机名如:127.0.0.1


def timeout_exception():
    return (500, "run_gvm deal timeout")


def set_timeout(num, callback):
    def wrape(func):
        def handle(signum, frame):
            raise ("运行超时")

        def toDo(*args, **kwargs):
            try:
                signal.signal(signal.SIGALRM, handle)
                signal.alarm(num)  # 开启闹钟信号
                rs = func(*args, **kwargs)
                signal.alarm(0)  # 关闭闹钟信号
                return rs
            except:
                callback()

        return toDo

    return wrape


class Resquest(BaseHTTPRequestHandler):
    timeout = 10
    hostname = '127.0.0.1'
    port = 9390
    username = ''
    password = ''

    def handler(self, code, response):
        self.send_response(code)
        self.send_header('Content-type', 'application/txt')
        self.end_headers()
        self.wfile.write(response.encode())

    def timeout_callback(self, p):
        print('exe time out call back')
        print(p.id)
        try:
            p.kill()
        except Exception as error:
            print(error)

    def run_cmd(self, cmd):
        print('running:%s' % cmd)
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=os.getcwd(), shell=True)
        my_timer = Timer(self.timeout, self.timeout_callback, [p])
        my_timer.start()
        try:
            print("start to count timeout; timeout set to be %d \n" % (self.timeout,))
            out, stderr = p.communicate()
            # exit_code = p.returncode
        finally:
            my_timer.cancel()
            return out.decode()

    @set_timeout(gvm_order_timeout, timeout_exception)
    def run_app(self, node):
        return 200, "Parameters are missing"

    def do_GET(self):
        print(self.requestline)
        if self.path != '/hello':
            self.handler(404, "Parameters are missing")
            return
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(data).encode())

    def do_POST(self):
        # print(self.headers)
        # print(self.command)
        # print(self.path, len(self.path), type(self.path))
        if self.headers['Referer'] != 'localHost':
            self.handler(404, "Parameters are missing")
            return
        if self.path == '/':
            self.path = '/tls'
        if self.path != '/tls' and self.path != '/ssh' and self.path != '/sock':
            self.handler(405, "Request method error")
            return
        # 读取请求体内容
        req_datas = self.rfile.read(int(self.headers['content-length']))
        # print(req_datas.decode())
        node = Node()
        node.gvm_cmd = req_datas.decode()
        node.host_name = self.headers['host_name']

        code, data = self.run_app(node)
        data_len = len(data)
        if data_len == 0 or data == "":
            self.handler(405, "response is null")
            return

        self.send_response(code)
        self.send_header('Content-type', 'application/xml')
        self.end_headers()
        # 返回信息量大 需分批写
        offset = 0
        n = data_len % 1024
        m = int(data_len / 1024)
        # print(data_len, m , n)
        for i in range(m):
            data_tmp = data[offset: offset + 1024]
            offset = offset + 1024
            self.wfile.write(data_tmp.encode())
        data_tmp = data[offset:]
        self.wfile.write(data_tmp.encode())


# 可以多线程,多队列的方式,
if __name__ == '__main__':
    server = HTTPServer(host, Resquest)
    server.timeout = 10
    print("Starting server, listen at: %s:%s" % host)
    # server.serve_forever()
    while True:
        server.handle_request()

http-server 基于ThreadingMixIn实现多线程处理:


from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import subprocess
import os
import time
from threading import Timer
import getpass
import logging
import os.path
import sys
import signal
import codecs
from socketserver import ThreadingMixIn
# from signal import signal, SIGPIPE, SIG_DFL


sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())

data = {'result': 'this is a agent!!'}
# 监听主机 & 端口
host = ('0.0.0.0', 4322)
# gvm指令请求超时时间,单位秒
gvm_order_timeout = 6


class Node():
    def __init__(self):
        self.connect_method = ""  # 连接方法
        self.host_name = "127.0.0.1"  # 主机名如:127.0.0.1


def timeout_exception():
    return (500, "run_gvm deal timeout")


def set_timeout(num, callback):
    def wrape(func):
        def handle(signum, frame):
            raise ("运行超时")

        def toDo(*args, **kwargs):
            try:
                signal.signal(signal.SIGALRM, handle)
                signal.alarm(num)  # 开启闹钟信号
                rs = func(*args, **kwargs)
                signal.alarm(0)  # 关闭闹钟信号
                return rs
            except:
                callback()

        return toDo

    return wrape


class Resquest(BaseHTTPRequestHandler):
    timeout = 10
    hostname = '127.0.0.1'
    port = 9390
    username = ''
    password = ''

    def handler(self, code, response):
        self.send_response(code)
        self.send_header('Content-type', 'application/txt')
        self.end_headers()
        self.wfile.write(response.encode())

    def timeout_callback(self, p):
        print('exe time out call back')
        print(p.id)
        try:
            p.kill()
        except Exception as error:
            print(error)

    def run_cmd(self, cmd):
        print('running:%s' % cmd)
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=os.getcwd(), shell=True)
        my_timer = Timer(self.timeout, self.timeout_callback, [p])
        my_timer.start()
        try:
            print("start to count timeout; timeout set to be %d \n" % (self.timeout,))
            out, stderr = p.communicate()
            # exit_code = p.returncode
        finally:
            my_timer.cancel()
            return out.decode()

    def run_app(self, node):
        print("demo1111")
        time.sleep(10)
        return 200, "Parameters are missing"

    def do_GET(self):
        print(self.requestline)
        if self.path != '/hello':
            self.handler(404, "Parameters are missing")
            return
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(data).encode())

    def do_POST(self):
        # print(self.headers)
        # print(self.command)
        # print(self.path, len(self.path), type(self.path))
        if self.headers['Referer'] != 'localHost':
            self.handler(404, "Parameters are missing")
            return
        if self.path == '/':
            self.path = '/tls'
        if self.path != '/tls' and self.path != '/ssh' and self.path != '/sock':
            self.handler(405, "Request method error")
            return
        # 读取请求体内容
        req_datas = self.rfile.read(int(self.headers['content-length']))
        # print(req_datas.decode())
        node = Node()
        node.gvm_cmd = req_datas.decode()
        node.host_name = self.headers['host_name']

        code, data = self.run_app(node)
        data_len = len(data)
        if data_len == 0 or data == "":
            self.handler(405, "response is null")
            return

        self.send_response(code)
        self.send_header('Content-type', 'application/xml')
        self.end_headers()
        # 返回信息量大 需分批写
        offset = 0
        n = data_len % 1024
        m = int(data_len / 1024)
        # print(data_len, m , n)
        for i in range(m):
            data_tmp = data[offset: offset + 1024]
            offset = offset + 1024
            self.wfile.write(data_tmp.encode())
        data_tmp = data[offset:]
        self.wfile.write(data_tmp.encode())

class ThreadingHttpServer(ThreadingMixIn, HTTPServer):
    pass

# 可以多线程,多队列的方式,
if __name__ == '__main__':
    #server = HTTPServer(host, Resquest)
    server = ThreadingHttpServer(host, Resquest)
    server.timeout = 10
    print("Starting server, listen at: %s:%s" % host)
    server.serve_forever()
    

client

	
import  requests

url = 'http://10.25.40.30:4321'
header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',
          'Accept': 'text / html,application / xml',
          'Referer': 'localHost',
          'Accept-Encoding': 'gzip, deflate',
          'username':'sysadmin',
         'password':'122'}

#data = "<get_version/>"
r = requests.post(url, headers=header, data=data, timeout=100)

Read More
 2019-07-17
NLP-信息收集

背景 涉及内容 一些示例 原文摘自: https://github.com/fighting41love/funNLP背景最近需要从文本中抽取结构化信息,用到了很多github上的包,遂整理了一下,后续会不断更新。很多包非常有趣,值得收藏,满足大家的收集癖!涉及内容 中英文敏感词、语言检测、中外手机/...

Read More