pproxy: improve ipv6 support

This commit is contained in:
Oleksii Shevchuk 2019-12-31 09:29:44 +02:00
parent bb56c635cb
commit 03d3dd6d56
6 changed files with 96 additions and 41 deletions

View File

@ -34,9 +34,11 @@ REQUEST_TCP_LISTENER = 2
REQUEST_KCP_LISTENER = 3
REQUEST_TLS_LISTENER = 4
class OffloadProxyCommonError(Exception):
pass
class MsgPackMessages(object):
def __init__(self, conn):
self._conn = conn
@ -59,6 +61,7 @@ class MsgPackMessages(object):
datalen_b = struct.pack('>I', datalen)
self._conn.sendall(datalen_b + data)
class PupyOffloadDNS(threading.Thread):
QTYPE = QTYPE.reverse
@ -135,6 +138,7 @@ class PupyOffloadDNS(threading.Thread):
if self.handler:
self.handler.finished.set()
class PupyOffloadSocket(object):
def __init__(self, sock, lhost, lport, rhost, rport):
self._sock = sock
@ -152,6 +156,7 @@ class PupyOffloadSocket(object):
return getattr(self, attr)
return getattr(self._sock, attr)
class PupyOffloadAcceptor(object):
def __init__(self, manager, proto, port=None, extra={}, mtu=0):
self._manager = manager
@ -239,8 +244,19 @@ class PupyOffloadAcceptor(object):
class PupyOffloadManager(object):
def __init__(self, server, ca, key, crt, via):
if ':' in server:
host, port = server.rsplit(':', 1)
if server.startswith('['):
ipv6_end = server.index(']')
host = server[1:ipv6_end]
rest = server[ipv6_end:]
if ':' in rest:
_, port = rest.rsplit(':', 1)
else:
raise OffloadProxyCommonError('Invalid server specification')
else:
host, port = server.rsplit(':', 1)
self._server = (host, int(port))
elif len(server) == 2:
self._server = server
else:

View File

@ -309,15 +309,23 @@ class Listener(Thread):
self.close()
def __str__(self):
if self.external:
external = self.external
if ':' in external:
external = '[' + external + ']'
else:
external = ''
if self.port == 0:
return '{}: pproxy:{}:{}'.format(
self.name, self.external, self.external_port
self.name, external, self.external_port
)
result = str(self.port)
if self.address:
result = '{}:{}'.format(
self.address if not self.ipv6 else '[{}]'.format(self.address),
self.address if not self.ipv6 and ':' not in self.address
else '[{}]'.format(self.address),
self.port
)
@ -326,7 +334,7 @@ class Listener(Thread):
result = '0.0.0.0:{}'.format(result)
result = 'Remote: {}:{} -> Local: {}'.format(
self.external, self.external_port, result
external, self.external_port, result
)
if self.kwargs:
@ -627,6 +635,9 @@ class PupyServer(object):
except:
client_ip, client_port = '0.0.0.0', 0
if ':' in client_ip:
client_ip = '[' + client_ip + ']'
remote = ' ({}:{})'.format(client_ip, client_port)
user = client_info.get('user', '?')

View File

@ -120,12 +120,25 @@ func (d *Daemon) handle(conn net.Conn) {
d.DNSLock.Unlock()
case INFO:
ip := GetOutboundIP()
var ip string
if CheckExternalBindHostIP() {
ip = ExternalBindHost
}
if string(ip[0]) == "[" {
ip = ip[1 : len(ip)-1]
}
log.Warning("Request: External IP:", ip)
log.Warning("Request: External IP:", ip, " (Manual)")
} else {
ipv4 := GetOutboundIPv4()
ipv6 := GetOutboundIPv6()
log.Warning(
"Request: External IPv4:", ipv4,
" IPv6:", ipv6, " (Auto)")
ip = ipv4
}
SendMessage(conn, &IPInfo{
IP: ip,

View File

@ -16,7 +16,7 @@ import (
log "github.com/sirupsen/logrus"
)
func GetOutboundIP() string {
func GetOutboundIPv4() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
@ -28,7 +28,24 @@ func GetOutboundIP() string {
return localAddr.IP.String()
}
func GetOutboundIPv6() string {
conn, err := net.Dial("udp", "[2001:4860:4860::8888]:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String()
}
func CheckExternalBindHostIP() bool {
host := ExternalBindHost
if string(host[0]) == "[" {
host = ExternalBindHost[1 : len(ExternalBindHost)-1]
}
ifaces, err := net.Interfaces()
if err != nil {
return false
@ -51,7 +68,7 @@ func CheckExternalBindHostIP() bool {
}
// process IP address
if ip.String() == ExternalBindHost {
if ip.String() == host {
return true
}
}
@ -69,7 +86,7 @@ func getCN() string {
return ExternalBindHost
default:
return GetOutboundIP()
return GetOutboundIPv4()
}
}

View File

@ -1,7 +1,7 @@
package main
import (
"fmt"
"net"
"path"
"io/ioutil"
@ -18,18 +18,18 @@ import (
)
var (
ProxyBindHost = "0.0.0.0"
ExternalBindHost = "0.0.0.0"
ProxyBindPort uint = 9876
DnsBindPort uint = 5454
ProxyHostname = ""
UDPSize uint = 1400
ListenerCA = path.Join("..", "crypto", "proxy-ca.crt")
ListenerCAKey = path.Join("..", "crypto", "proxy-ca.key")
ListenerKey = path.Join("..", "crypto", "proxy.key")
ListenerCert = path.Join("..", "crypto", "proxy.crt")
ClientKey = path.Join("..", "crypto", "proxy-client.key")
ClientCert = path.Join("..", "crypto", "proxy-client.crt")
ProxyBindHost = "[::]:9876"
ExternalBindHost = "::"
DnsBindPort uint = 5454
ProxyHostname = ""
UDPSize uint = 1400
ListenerCA = path.Join("..", "crypto", "proxy-ca.crt")
ListenerCAKey = path.Join("..", "crypto", "proxy-ca.key")
ListenerKey = path.Join("..", "crypto", "proxy.key")
ListenerCert = path.Join("..", "crypto", "proxy.crt")
ClientKey = path.Join("..", "crypto", "proxy-client.key")
ClientCert = path.Join("..", "crypto", "proxy-client.crt")
PortMaps []PortMap
@ -45,7 +45,6 @@ func init() {
portmap := ""
flag.StringVar(&ProxyBindHost, "listen-proxy", ProxyBindHost, "IP address to bind pupysh listener side")
flag.UintVar(&ProxyBindPort, "port-proxy", ProxyBindPort, "Port to bind pupysh listener side")
flag.StringVar(&ExternalBindHost, "listen", ExternalBindHost, "IP address to bind services listener side")
flag.UintVar(&DnsBindPort, "dns-port", DnsBindPort, "Port to bind DNS listeners (if any)")
flag.UintVar(&UDPSize, "udp-mtu-size", UDPSize, "MTU Size for DNS and KCP UDP Packets")
@ -115,22 +114,22 @@ func init() {
}
}
if strings.Index(ProxyBindHost, ":") == -1 {
if ExternalBindHost == "0.0.0.0" {
ExternalBindHost = ProxyBindHost
}
host, _, err := net.SplitHostPort(ExternalBindHost)
if err == nil && host != "" {
ExternalBindHost = host
}
ProxyBindHost = fmt.Sprintf("%s:%d", ProxyBindHost, ProxyBindPort)
} else {
if ExternalBindHost == "0.0.0.0" {
ExternalBindHost = strings.SplitN(ProxyBindHost, ":", 1)[0]
}
if ExternalBindHost == "" {
ExternalBindHost = "::"
}
if strings.Index(ExternalBindHost, ":") != -1 {
log.Fatalln("External IP address should be specified without port")
ExternalBindHost = "[" + ExternalBindHost + "]"
}
log.Warn("Mapper binds to ", ExternalBindHost)
log.Warn("Proxy binds to ", ProxyBindHost)
if generate {
log.Warn("Genrating NEW keys")
generateKeys()

View File

@ -5,7 +5,6 @@ import (
"io"
"net"
"strconv"
"strings"
"time"
@ -107,16 +106,16 @@ func NewNetForwarder(pproxy, remote net.Conn) *NetForwarder {
}
func (n *NetForwarder) sendRemoteConnectionInfo() error {
localAddr := strings.Split(n.remote.LocalAddr().String(), ":")
remoteAddr := strings.Split(n.remote.RemoteAddr().String(), ":")
localAddr, localPortS, _ := net.SplitHostPort(n.remote.LocalAddr().String())
remoteAddr, remotePortS, _ := net.SplitHostPort(n.remote.RemoteAddr().String())
localPort, _ := strconv.Atoi(localAddr[1])
remotePort, _ := strconv.Atoi(remoteAddr[1])
localPort, _ := strconv.Atoi(localPortS)
remotePort, _ := strconv.Atoi(remotePortS)
return SendMessage(n.pproxy, ConnectionAcceptHeader{
LocalHost: localAddr[0],
LocalHost: localAddr,
LocalPort: localPort,
RemoteHost: remoteAddr[0],
RemoteHost: remoteAddr,
RemotePort: remotePort,
})
}