Support redirect rule (#145)
Syntax: match_hostname_regex:port(* means match all port)#redirect_dist_host:redirect_port and in the config.json(user-config.json) redirect param should be a list, for example ``` "redirect": ["*:8080#zhaoj.in:80","zhaojin97.cn:80#127.0.0.1:80","*#pku.edu.cn:80"] ``` This example means abnormal connection which connect to port 8080 will be redirected to zhaoj.in:80,and if there a http request with hostname zhaojin97.cn(you can set hosts file to test it) will be redirected to 127.0.0.1:80,and the rest of abnormal connection will be redirect to pku.edu.cn:80
This commit is contained in:
parent
403ce5da58
commit
c7815a0ee8
2 changed files with 73 additions and 31 deletions
|
@ -22,6 +22,7 @@ import socket
|
|||
import struct
|
||||
import logging
|
||||
import binascii
|
||||
import re
|
||||
|
||||
def compat_ord(s):
|
||||
if type(s) == int:
|
||||
|
@ -118,6 +119,13 @@ def is_ip(address):
|
|||
return False
|
||||
|
||||
|
||||
def match_regex(regex, text):
|
||||
regex = re.compile(regex)
|
||||
for item in regex.findall(text):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def patch_socket():
|
||||
if not hasattr(socket, 'inet_pton'):
|
||||
socket.inet_pton = inet_pton
|
||||
|
|
|
@ -151,7 +151,7 @@ class TCPRelayHandler(object):
|
|||
server_info.tcp_mss = 1460
|
||||
self._protocol.set_server_info(server_info)
|
||||
|
||||
self._redir_list = config.get('redirect', ["0.0.0.0:0"])
|
||||
self._redir_list = config.get('redirect', ["*#0.0.0.0:0"])
|
||||
self._bind = config.get('out_bind', '')
|
||||
self._bindv6 = config.get('out_bindv6', '')
|
||||
self._ignore_bind_list = config.get('ignore_bind', [])
|
||||
|
@ -347,7 +347,13 @@ class TCPRelayHandler(object):
|
|||
return True
|
||||
|
||||
def _get_redirect_host(self, client_address, ogn_data):
|
||||
host_list = self._redir_list or ["0.0.0.0:0"]
|
||||
host_list = self._redir_list or ["*#0.0.0.0:0"]
|
||||
|
||||
if type(host_list) != list:
|
||||
host_list = [host_list]
|
||||
|
||||
items_sum = common.to_str(host_list[0]).rsplit('#', 1)
|
||||
if len(items_sum) < 2:
|
||||
hash_code = binascii.crc32(ogn_data)
|
||||
addrs = socket.getaddrinfo(client_address[0], client_address[1], 0, socket.SOCK_STREAM, socket.SOL_TCP)
|
||||
af, socktype, proto, canonname, sa = addrs[0]
|
||||
|
@ -361,8 +367,6 @@ class TCPRelayHandler(object):
|
|||
|
||||
host_port = []
|
||||
match_port = False
|
||||
if type(host_list) != list:
|
||||
host_list = [host_list]
|
||||
for host in host_list:
|
||||
items = common.to_str(host).rsplit(':', 1)
|
||||
if len(items) > 1:
|
||||
|
@ -385,6 +389,36 @@ class TCPRelayHandler(object):
|
|||
|
||||
return host_port[((hash_code & 0xffffffff) + addr) % len(host_port)]
|
||||
|
||||
else:
|
||||
host_port = []
|
||||
for host in host_list:
|
||||
items_sum = common.to_str(host).rsplit('#', 1)
|
||||
items_match = common.to_str(items_sum[0]).rsplit(':', 1)
|
||||
items = common.to_str(items_sum[1]).rsplit(':', 1)
|
||||
if len(items_match) > 1:
|
||||
if self._server._listen_port != int(items_match[1]):
|
||||
continue
|
||||
match_port = 0
|
||||
if len(items_match) > 1:
|
||||
if items_match[1] != "*":
|
||||
try:
|
||||
match_port = int(items_match[1])
|
||||
except:
|
||||
pass
|
||||
if items_match[0] != "*" and common.match_regex(items_match[0], ogn_data) == False and \
|
||||
not (match_port == self._server._listen_port or match_port == 0):
|
||||
continue
|
||||
if len(items) > 1:
|
||||
try:
|
||||
port = int(items[1])
|
||||
return (items[0], port)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
return (items[0], 80)
|
||||
|
||||
return ("0.0.0.0", 0)
|
||||
|
||||
def _handel_protocol_error(self, client_address, ogn_data):
|
||||
logging.warn("Protocol ERROR, TCP ogn data %s from %s:%d via port %d" % (binascii.hexlify(ogn_data), client_address[0], client_address[1], self._server._listen_port))
|
||||
self._encrypt_correct = False
|
||||
|
|
Loading…
Add table
Reference in a new issue