ipv6 support

This commit is contained in:
n1nj4sec 2016-05-27 18:17:03 +02:00
parent c9a19cbd6e
commit e27887540d
11 changed files with 75 additions and 34 deletions

View File

@ -10,19 +10,18 @@ class PupyClient(object):
raise NotImplementedError("connect not implemented")
class PupyTCPClient(PupyClient):
def __init__(self, family = socket.AF_INET, socktype = socket.SOCK_STREAM, proto = 0, timeout = 3, nodelay = False, keepalive = False):
def __init__(self, family = socket.AF_UNSPEC, socktype = socket.SOCK_STREAM, timeout = 3, nodelay = False, keepalive = False):
super(PupyTCPClient, self).__init__()
self.sock=None
self.family=socket.AF_INET
self.socktype=socket.SOCK_STREAM
self.proto=proto
self.family=family
self.socktype=socktype
self.timeout=timeout
self.nodelay=nodelay
self.keepalive=keepalive
def connect(self, host, port):
family, socktype, proto, _, sockaddr = socket.getaddrinfo(host, port, self.family, self.socktype, self.proto)[0]
family, socktype, proto, _, sockaddr = socket.getaddrinfo(host, port, self.family, self.socktype)[0]
s = socket.socket(family, socktype, proto)
s.settimeout(self.timeout)
s.connect(sockaddr)
@ -32,7 +31,7 @@ class PupyTCPClient(PupyClient):
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# Linux specific: after 10 idle minutes, start sending keepalives every 5 minutes.
# Drop connection after 10 failed keepalives
if hasattr(socket, "TCP_KEEPIDLE") and hasattr(socket, "TCP_KEEPINTVL") and hasattr(socket, "TCP_KEEPCNT") :
if hasattr(socket, "TCP_KEEPIDLE") and hasattr(socket, "TCP_KEEPINTVL") and hasattr(socket, "TCP_KEEPCNT"):
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10 * 60)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 5 * 60)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 10)
@ -57,7 +56,7 @@ class PupyProxifiedTCPClient(PupyTCPClient):
def connect(self, host, port):
socks.set_default_proxy(proxy_type=socks.PROXY_TYPES[self.proxy_type], addr=self.proxy_addr, port=self.proxy_port, rdns=True, username=self.proxy_username, password=self.proxy_password)
family, socktype, proto, _, sockaddr = socket.getaddrinfo(host, port, self.family, self.socktype, self.proto)[0]
family, socktype, proto, _, sockaddr = socket.getaddrinfo(host, port, self.family, self.socktype)[0]
s=socks.socksocket(family, socktype, proto)
s.settimeout(self.timeout)
s.connect(sockaddr)
@ -67,7 +66,7 @@ class PupyProxifiedTCPClient(PupyTCPClient):
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# Linux specific: after 10 idle minutes, start sending keepalives every 5 minutes.
# Drop connection after 10 failed keepalives
if hasattr(socket, "TCP_KEEPIDLE") and hasattr(socket, "TCP_KEEPINTVL") and hasattr(socket, "TCP_KEEPCNT") :
if hasattr(socket, "TCP_KEEPIDLE") and hasattr(socket, "TCP_KEEPINTVL") and hasattr(socket, "TCP_KEEPCNT"):
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10 * 60)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 5 * 60)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 10)

View File

@ -6,14 +6,19 @@ import os
import logging
from .servers import PupyTCPServer
from .clients import PupyTCPClient, PupySSLClient, PupyProxifiedTCPClient, PupyProxifiedSSLClient
from .transports import dummy, b64
from .transports.obfs3 import obfs3
from .transports import dummy, b64, http
try:
from .transports.obfs3 import obfs3
except ImportError as e:
#to make pupy works even without scramblesuit dependencies
logging.warning("%s. The obfs3 transport has been disabled."%e)
obfs3=None
try:
from .transports.scramblesuit import scramblesuit
except ImportError as e:
#to make pupy works even without scramblesuit dependencies
logging.warning("%s. The transport has been disabled."%e)
logging.warning("%s. The scramblesuit transport has been disabled."%e)
scramblesuit=None
from .streams import PupySocketStream
from .launchers.simple import SimpleLauncher
@ -38,8 +43,8 @@ scramblesuit_passwd="th!s_iS_pupy_sct_k3y"
transports={}
launchers={}
transports["tcp_ssl"]={
"info" : "Simple reverse TCP payload with SSL",
transports["ssl"]={
"info" : "TCP transport wrapped with SSL",
"server" : PupyTCPServer,
"client": PupySSLClient,
"client_kwargs" : {},
@ -50,8 +55,8 @@ transports["tcp_ssl"]={
"client_transport_kwargs": {},
"server_transport_kwargs": {},
}
transports["tcp_ssl_proxy"]={
"info" : "Simple reverse TCP payload with SSL passing through a SOCKS4/SOCKS5/HTTP proxy",
transports["ssl_proxy"]={
"info" : "TCP transport wrapped with SSL and passing through a SOCKS4/SOCKS5/HTTP proxy",
"server" : PupyTCPServer,
"client": PupyProxifiedSSLClient,
"client_kwargs" : {'proxy_addr': None, 'proxy_port': None, 'proxy_type':'HTTP'},
@ -63,7 +68,7 @@ transports["tcp_ssl_proxy"]={
"server_transport_kwargs": {},
}
transports["tcp_cleartext"]={
"info" : "Simple reverse TCP payload (cleartext)",
"info" : "Simple TCP transport transmitting in cleartext",
"server" : PupyTCPServer,
"client": PupyTCPClient,
"client_kwargs" : {},
@ -75,7 +80,7 @@ transports["tcp_cleartext"]={
"server_transport_kwargs": {},
}
transports["tcp_cleartext_proxy"]={
"info" : "Simple reverse TCP payload in cleartext passing through a SOCKS4/SOCKS5/HTTP proxy",
"info" : "TCP transport transmitting in cleartext and passing through a SOCKS4/SOCKS5/HTTP proxy",
"server" : PupyTCPServer,
"client": PupyProxifiedTCPClient,
"client_kwargs" : {'proxy_addr':'127.0.0.1', 'proxy_port':8080, 'proxy_type':'HTTP'},
@ -87,7 +92,7 @@ transports["tcp_cleartext_proxy"]={
"server_transport_kwargs": {},
}
transports["tcp_base64"]={
"info" : "Reverse TCP payload with base64 encoding",
"info" : "TCP transport with base64 encoding",
"server" : PupyTCPServer,
"client": PupyTCPClient,
"client_kwargs" : {},
@ -98,21 +103,37 @@ transports["tcp_base64"]={
"client_transport_kwargs": {},
"server_transport_kwargs": {},
}
transports["obfs3"]={
"info" : "Reverse TCP Payload using obfs3 transport",
"""
transports["http_cleartext"]={
"info" : "TCP transport using HTTP with base64 encoded payloads",
"server" : PupyTCPServer,
"client": PupyTCPClient,
"client_kwargs" : {},
"authenticator" : None,
"stream": PupySocketStream ,
"client_transport" : obfs3.Obfs3Client,
"server_transport" : obfs3.Obfs3Server,
"client_transport" : http.PupyHTTPClient,
"server_transport" : http.PupyHTTPServer,
"client_transport_kwargs": {},
"server_transport_kwargs": {},
}
"""
if obfs3:
transports["obfs3"]={
"info" : "TCP transport using obfsproxy's obfs3 transport",
"server" : PupyTCPServer,
"client": PupyTCPClient,
"client_kwargs" : {},
"authenticator" : None,
"stream": PupySocketStream ,
"client_transport" : obfs3.Obfs3Client,
"server_transport" : obfs3.Obfs3Server,
"client_transport_kwargs": {},
"server_transport_kwargs": {},
}
if scramblesuit:
transports["scramblesuit"]={
"info" : "Reverse TCP Payload using scramblesuit transport",
"info" : "TCP transport using the obfsproxy's scramblesuit transport",
"server" : PupyTCPServer,
"client": PupyTCPClient,
"client_kwargs" : {},

View File

@ -136,7 +136,7 @@ class AutoProxyLauncher(BaseLauncher):
def init_argparse(self):
self.arg_parser = LauncherArgumentParser(prog="auto_proxy", description=self.__doc__)
self.arg_parser.add_argument('--host', metavar='<host:port>', required=True, help='host:port of the pupy server to connect to')
self.arg_parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys() if not x.endswith("_proxy")], default="tcp_ssl", help="the transport to use ! (the server needs to be configured with the same transport) ")
self.arg_parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys() if not x.endswith("_proxy")], default="ssl", help="the transport to use ! (the server needs to be configured with the same transport) ")
self.arg_parser.add_argument('transport_args', nargs=argparse.REMAINDER, help="change some transport arguments ex for proxy transports: proxy_addr=192.168.0.1 proxy_port=8080 proxy_type=HTTP")
def parse_args(self, args):
self.args=self.arg_parser.parse_args(args)

View File

@ -17,7 +17,7 @@ class BindLauncher(BaseLauncher):
self.arg_parser = LauncherArgumentParser(prog="bind", description=self.__doc__)
self.arg_parser.add_argument('--port', metavar='<port>', type=int, required=True, help='the port to bind on')
self.arg_parser.add_argument('--host', metavar='<ip>', default='0.0.0.0', help='the ip to listen on (default 0.0.0.0)')
self.arg_parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys()], default="tcp_ssl", help="the transport to use ! (the pupysh.sh --connect will need to be configured with the same transport) ")
self.arg_parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys()], default="ssl", help="the transport to use ! (the pupysh.sh --connect will need to be configured with the same transport) ")
self.arg_parser.add_argument('--password', default=config.get("pupyd", "bind_password").strip(), help="Add a password to connect to the bind payload. WARNING: it could not be safe, a safer alternative would be to use rpyc authenticators with SSL client certificates")
self.arg_parser.add_argument('transport_args', nargs=argparse.REMAINDER, help="change some transport arguments")

View File

@ -9,7 +9,7 @@ class SimpleLauncher(BaseLauncher):
def init_argparse(self):
self.arg_parser = LauncherArgumentParser(prog="connect", description=self.__doc__)
self.arg_parser.add_argument('--host', metavar='<host:port>', required=True, help='host:port of the pupy server to connect to')
self.arg_parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys()], default="tcp_ssl", help="the transport to use ! (the server needs to be configured with the same transport) ")
self.arg_parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys()], default="ssl", help="the transport to use ! (the server needs to be configured with the same transport) ")
self.arg_parser.add_argument('transport_args', nargs=argparse.REMAINDER, help="change some transport arguments ex for proxy transports: proxy_addr=192.168.0.1 proxy_port=8080 proxy_type=HTTP")
def parse_args(self, args):
self.args=self.arg_parser.parse_args(args)

View File

@ -35,7 +35,9 @@ class PupyTCPServer(ThreadPoolServer):
else:
credentials = None
# build a connection
h, p = sock.getpeername()
addrinfo = sock.getpeername()
h=addrinfo[0]
p=addrinfo[1]
config = dict(self.protocol_config, credentials=credentials, connid="%s:%d"%(h, p))
return Connection(self.service, Channel(self.stream_class(sock, self.transport_class, self.transport_kwargs)), config=config)

View File

@ -21,6 +21,12 @@ class addGetPeer(object):
def getPeer(self):
return self.peer
def monitor(up, down):
while True:
print "up: %s"%len(up)
print "down: %s"%len(down)
time.sleep(2)
class PupySocketStream(SocketStream):
def __init__(self, sock, transport_class, transport_kwargs={}):
super(PupySocketStream, self).__init__(sock)
@ -31,6 +37,10 @@ class PupySocketStream(SocketStream):
self.upstream=Buffer(transport_func=addGetPeer(("127.0.0.1", 443)))
self.downstream=Buffer(on_write=self._upstream_recv, transport_func=addGetPeer(sock.getpeername()))
t=threading.Thread(target=monitor, args=(self.upstream, self.downstream))
t.daemon=True
t.start()
self.transport=transport_class(self, **transport_kwargs)
self.on_connect()
#self.async_read_thread=threading.Thread(target=self._downstream_recv_loop)

View File

@ -1,6 +1,8 @@
[pupyd]
address = 0.0.0.0
#listen on all interfaces by default
#address = 192.168.0.1
port = 443
ipv6 = true
keyfile = crypto/server.pem
certfile = crypto/cert.pem

View File

@ -176,8 +176,8 @@ class PupyCmd(cmd.Cmd):
self.intro += color(BANNER_INFO, 'darkgrey')
if sys.platform=="win32":
self.intro+="\n"+self.format_warning("You are running Pupy server on Windows. Pupy server works best on linux. Pupy server on windows has not been really tested and there is probably a lot of bugs. I try my best to code in a portable way but it don't always find the time to fix everything. If you find the courage to patch non portable code, I will gladly accept push requests ! :)\n")
self.intro += "\n"+self.format_srvinfo("Server started on %s:%s with transport %s%s"%(self.pupsrv.address, self.pupsrv.port, self.pupsrv.transport, (" and transport_args=%s"%repr(self.pupsrv.transport_kwargs) if self.pupsrv.transport_kwargs else ""))).rstrip("\n")
self.intro += "\n"+self.format_srvinfo("Server started on%s port %s with transport %s%s"%((" "+self.pupsrv.address if self.pupsrv.address else ""), self.pupsrv.port, self.pupsrv.transport, (" and transport_args=%s"%repr(self.pupsrv.transport_kwargs) if self.pupsrv.transport_kwargs else ""))).rstrip("\n")
self.raw_prompt= color('>> ','blue')
self.prompt = color('>> ','blue', prompt=True)

View File

@ -42,7 +42,7 @@ import os.path
class PupyServer(threading.Thread):
def __init__(self, transport, transport_kwargs, port=None):
def __init__(self, transport, transport_kwargs, port=None, ipv6=None):
super(PupyServer, self).__init__()
self.daemon=True
self.server=None
@ -58,7 +58,14 @@ class PupyServer(threading.Thread):
self.port=self.config.getint("pupyd", "port")
else:
self.port=port
self.address=self.config.get("pupyd", "address")
if ipv6 is None:
self.ipv6=self.config.getboolean("pupyd", "ipv6")
else:
self.ipv6=ipv6
try:
self.address=self.config.get("pupyd", "address")
except configparser.NoOptionError:
self.address=''
self.handler=None
self.handler_registered=threading.Event()
self.transport=transport
@ -341,7 +348,7 @@ class PupyServer(threading.Thread):
authenticator=t['authenticator']()
else:
authenticator=None
self.server = t['server'](PupyService.PupyService, port = self.port, hostname=self.address, authenticator=authenticator, stream=t['stream'], transport=t['server_transport'], transport_kwargs=transport_kwargs)
self.server = t['server'](PupyService.PupyService, port = self.port, hostname=self.address, authenticator=authenticator, stream=t['stream'], transport=t['server_transport'], transport_kwargs=transport_kwargs, ipv6=self.ipv6)
self.server.start()

View File

@ -43,7 +43,7 @@ if __name__=="__main__":
parser = argparse.ArgumentParser(prog='ptrconsole', description="Pupy console")
parser.add_argument('--log-lvl', '--lvl', help="change log verbosity", dest="loglevel", choices=["DEBUG","INFO","WARNING","ERROR"], default="WARNING")
parser.add_argument('--version', help="print version and exit", action='store_true')
parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys()], default='tcp_ssl', help="change the transport ! :-)")
parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys()], default='ssl', help="change the transport ! :-)")
parser.add_argument('--transport-args', help="... --transport-args 'OPTION1=value OPTION2=val ...' ...")
parser.add_argument('--port', '-p', help="change the listening port", type=int)
args=parser.parse_args()