跳转到主要内容

UNIX WSGI HTTP服务器

项目描述

tproxy

tproxy是一个简单的TCP路由代理(第7层),基于Gevent构建,允许您用Python配置路由逻辑。它深受proxy machine的启发,但有一些独特功能,例如从Gunicorn借用到的预fork工作模型。

安装

tproxy需要Python 2.x >= 2.5。计划支持Python 3.x。

$ pip install gevent
$ pip install tproxy

从源安装

$ git clone git://github.com/benoitc/tproxy.git
$ cd tproxy
$ pip install -r requirements.txt
$ python setup.py install

通过运行命令行测试您的安装

$ tproxy examples/transparent.py

然后转到http://127.0.0.1:5000,您应该看到谷歌主页。

用法

$ tproxy -h

Usage: tproxy [OPTIONS] script_path

Options:
  --version                     show program's version number and exit
  -h, --help                    show this help message and exit
  --log-file=FILE               The log file to write to. [-]
  --log-level=LEVEL             The granularity of log outputs. [info]
  --log-config=FILE             The log config file to use. [None]
  -n STRING, --name=STRING      A base to use with setproctitle for process naming.
                                [None]
  -D, --daemon                  Daemonize the tproxy process. [False]
  -p FILE, --pid=FILE           A filename to use for the PID file. [None]
  -u USER, --user=USER          Switch worker processes to run as this user. [501]
  -g GROUP, --group=GROUP
                                Switch worker process to run as this group. [20]
  -m INT, --umask=INT           A bit mask for the file mode on files written by
                                tproxy. [0]
  -b ADDRESS, --bind=ADDRESS    The socket to bind. [127.0.0.1:8000]
  --backlog=INT                 The maximum number of pending connections.     [2048]
  --ssl-keyfile=STRING          Ssl key file [None]
  --ssl-certfile=STRING         Ssl ca certs file. contains concatenated
                                "certification [None]
  --ssl-ca-certs=STRING         Ssl ca certs file. contains concatenated
                                "certification [None]
  --ssl-cert-reqs=INT           Specifies whether a certificate is required from the
                                other [0]
  -w INT, --workers=INT         The number of worker process for handling requests. [1]
  --worker-connections=INT      The maximum number of simultaneous clients per worker.
                                [1000]
  -t INT, --timeout=INT         Workers silent for more than this many seconds are
                                killed and restarted. [30]

信号

QUIT    -   Graceful shutdown. Stop accepting connections immediatly
            and wait until all connections close

TERM    -   Fast shutdown. Stop accepting and close all conections
            after 10s.
INT     -   Same as TERM

HUP     -   Graceful reloading. Reload all workers with the new code
            in your routing script.

USR2    -   Upgrade tproxy on the fly

TTIN    -   Increase the number of worker from 1

TTOU    -   Decrease the number of worker from 1

路由脚本示例

import re
re_host = re.compile("Host:\s*(.*)\r\n")

class CouchDBRouter(object):
    # look at the routing table and return a couchdb node to use
    def lookup(self, name):
        """ do something """

router = CouchDBRouter()

# Perform content-aware routing based on the stream data. Here, the
# Host header information from the HTTP protocol is parsed to find the
# username and a lookup routine is run on the name to find the correct
# couchdb node. If no match can be made yet, do nothing with the
# connection. (make your own couchone server...)

def proxy(data):
    matches = re_host.findall(data)
    if matches:
        host = router.lookup(matches.pop())
        return {"remote": host}
    return None

18行内的SOCKS4代理示例

import socket
import struct

def proxy(data):
    if len(data) < 9:
        return

    command = ord(data[1])
    ip, port = socket.inet_ntoa(data[4:8]), struct.unpack(">H", data[2:4])[0]
    idx = data.index("\0")
    userid = data[8:idx]

    if command == 1: #connect
        return dict(remote="%s:%s" % (ip, port),
                reply="\0\x5a\0\0\0\0\0\0",
                data=data[idx:])
    else:
        return {"close": "\0\x5b\0\0\0\0\0\0"}

返回文件的示例

import os

WELCOME_FILE = os.path.join(os.path.dirname(__file__), "welcome.txt")

def proxy(data):
    fno = os.open(WELCOME_FILE, os.O_RDONLY)
    return {
            "file": fno,
            "reply": "HTTP/1.1 200 OK\r\n\r\n"
           }

有效的返回值

  • { “remote:”: string or tuple } - String是代理的服务器的主机:端口。

  • { “remote”: String, “data”: String} - 同上,但发送给定数据。

  • { “remote”: String, “data”: String, “reply”: String} - 同上,但向客户端发送给定数据作为回复。

  • None - 不做任何事情。

  • { “close”: True } - 关闭连接。

  • { “close”: String } - 在发送字符串后关闭连接。

  • { “file”: String } - 通过文件路径返回指定文件并关闭连接。

  • { “file”: String, “reply”: String } - 通过文件路径返回指定文件并关闭连接。

  • { “file”: Int, “reply”: String} - 与上述相同,但用给定数据回复客户端

  • { “file”: Int } - 返回指定文件描述符的文件

  • { “file”: Int, “reply”: String} - 与上述相同,但用给定数据回复客户端

注意事项

如果sendfile API可用,它将用于通过“file”命令发送文件。

“file”命令可以有2个可选参数

  • offset: 指定从文件中的哪个位置开始。

  • nbytes: 指定应发送多少字节的文件。

要为远程连接处理ssl,您可以添加以下可选参数

  • ssl: True或False,如果您想使用ssl连接

  • ssl_args: dict,可选ssl参数。阅读ssl文档以获取更多关于它们的信息。

处理错误

您可以通过在脚本中添加一个名为proxy_error的函数来轻松处理错误。

def proxy_error(client, e):
    pass

该函数将ClientConnection实例(当前连接)作为第一个参数,错误异常作为第二个参数。

重写请求与响应

tproxy的主要目标是允许您透明地路由tcp到您的应用程序。但有些情况下您需要做更多。例如,在HTTP 1.1中,您需要更改Host头,以确保远程HTTP服务器知道如何处理使用虚拟主机的情况。

为此,请将rewrite_request函数添加到您的函数中,以简单地重写客户端请求,将rewrite_response重写为远程响应。这两个函数都接受一个基于io.RawIOBase类的tproxy.rewrite.RewriteIO实例。

请参阅httprewrite.py示例,了解HTTP重写的示例。

项目详情


下载文件

下载您平台的文件。如果您不确定要选择哪一个,请了解更多关于安装包的信息。

源代码分发

tproxy-0.5.4.tar.gz (25.8 kB 查看散列)

上传时间 源代码

支持者:

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页