listener with tls transport layer

This commit is contained in:
changx 2018-10-29 16:18:51 +08:00
parent 5383ac4fc0
commit e27601f648
12 changed files with 223 additions and 140 deletions

View File

@ -81,7 +81,7 @@ func main() {
log.Fatal(err)
}
go local.ListenAndServe()
go local.ListenAndServe(nil)
}
sigCh := make(chan os.Signal, 1)

View File

@ -6,7 +6,6 @@ package http
import (
"bufio"
"bytes"
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
@ -28,17 +27,12 @@ type HTTP struct {
addr string
user string
password string
}
type HTTPS struct {
HTTP
tlsConfig *tls.Config
pretendAsWebServer bool
}
func init() {
proxy.RegisterDialer("http", NewHTTPDialer)
proxy.RegisterServer("http", NewHTTPServer)
proxy.RegisterServer("https", NewHTTPSServer)
}
// NewHTTP returns a http proxy.
@ -58,40 +52,17 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
addr: addr,
user: user,
password: pass,
pretendAsWebServer: false,
}
pretend := u.Query().Get("pretend")
if pretend != "" {
h.pretendAsWebServer = true
}
return h, nil
}
func NewHTTPS(s string, dialer proxy.Dialer) (*HTTPS, error) {
u, _ := url.Parse(s)
// TODO: cert=&key=
certFile := u.Query().Get("cert")
keyFile := u.Query().Get("key")
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
log.F("unabled load cert: %s, key %s", certFile, keyFile)
return nil, err
}
tlsConfig := tls.Config{
Certificates: []tls.Certificate{cert},
}
http, err := NewHTTP(s, dialer)
if err != nil {
return nil, err
}
https := &HTTPS{
HTTP: *http,
tlsConfig: &tlsConfig,
}
return https, nil
}
// NewHTTPDialer returns a http proxy dialer.
func NewHTTPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewHTTP(s, dialer)
@ -102,34 +73,9 @@ func NewHTTPServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewHTTP(s, dialer)
}
// NewHTTPSServer returns a https proxy server
func NewHTTPSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewHTTPS(s, dialer)
}
// ListenAndServe serves tls http proxy
func (s *HTTPS) ListenAndServe() {
l, err := tls.Listen("tcp", s.addr, s.tlsConfig)
if err != nil {
log.F("failed to listen on tls %s: %v", s.addr, err)
return
}
defer l.Close()
for {
c, err := l.Accept()
if err != nil {
log.F("[https] failed to accept: %v", err)
continue
}
go s.HTTP.Serve(c)
}
}
// ListenAndServe .
func (s *HTTP) ListenAndServe() {
func (s *HTTP) ListenAndServe(c net.Conn) {
if c == nil {
l, err := net.Listen("tcp", s.addr)
if err != nil {
log.F("failed to listen on %s: %v", s.addr, err)
@ -146,11 +92,13 @@ func (s *HTTP) ListenAndServe() {
continue
}
go s.Serve(c)
}
} else {
go s.Serve(c)
}
}
// Serve .
func (s *HTTP) Serve(c net.Conn) {
defer c.Close()
@ -166,8 +114,15 @@ func (s *HTTP) Serve(c net.Conn) {
return
}
if s.pretendAsWebServer {
fmt.Fprintf(c, "%s 404 Not Found\r\nServer: nginx\r\n\r\n", proto)
log.F("[http pretender] being accessed as web server from %s", c.RemoteAddr().String())
return
}
if method == "CONNECT" {
s.servHTTPS(method, requestURI, proto, c)
//c.Write([]byte("HTTP/1.1 405\nAllow: GET, POST, HEAD, OPTION, PATCH\nServer: vsps/1.2\nContent-Type: \n\n"))
return
}

View File

@ -31,6 +31,8 @@ type MixedProxy struct {
http *http.HTTP
socks5 *socks5.SOCKS5
pretendAsWebServer bool
}
func init() {
@ -45,9 +47,16 @@ func NewMixedProxy(s string, dialer proxy.Dialer) (*MixedProxy, error) {
return nil, err
}
pretend := u.Query().Get("pretend")
p := &MixedProxy{
dialer: dialer,
addr: u.Host,
pretendAsWebServer: false,
}
if pretend == "true" {
p.pretendAsWebServer = true
}
p.http, _ = http.NewHTTP(s, dialer)
@ -62,18 +71,18 @@ func NewMixedProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe .
func (p *MixedProxy) ListenAndServe() {
func (p *MixedProxy) ListenAndServe(c net.Conn) {
if c == nil {
go p.socks5.ListenAndServeUDP()
l, err := net.Listen("tcp", p.addr)
//l, err := net.Listen("tcp", p.addr)
if err != nil {
log.F("[mixed] failed to listen on %s: %v", p.addr, err)
return
}
log.F("[mixed] listening TCP on %s", p.addr)
for {
c, err := l.Accept()
if err != nil {
@ -81,6 +90,9 @@ func (p *MixedProxy) ListenAndServe() {
continue
}
go p.Serve(c)
}
} else {
go p.Serve(c)
}
}
@ -98,7 +110,7 @@ func (p *MixedProxy) Serve(c net.Conn) {
if p.socks5 != nil {
head, err := cc.Peek(1)
if err != nil {
log.F("[mixed] peek error: %s", err)
log.F("[mixed] socks5 peek error: %s", err)
return
}
@ -112,7 +124,7 @@ func (p *MixedProxy) Serve(c net.Conn) {
if p.http != nil {
head, err := cc.Peek(8)
if err != nil {
log.F("[mixed] peek error: %s", err)
log.F("[mixed] http peek error: %s", err)
return
}

View File

@ -64,7 +64,7 @@ func NewRedir6Server(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe .
func (s *RedirProxy) ListenAndServe() {
func (s *RedirProxy) ListenAndServe(_ net.Conn) {
l, err := net.Listen("tcp", s.addr)
if err != nil {
log.F("[redir] failed to listen on %s: %v", s.addr, err)

View File

@ -2,6 +2,7 @@ package proxy
import (
"errors"
"net"
"net/url"
"strings"
@ -11,7 +12,7 @@ import (
// Server interface
type Server interface {
// ListenAndServe as proxy server, use only in server mode.
ListenAndServe()
ListenAndServe(net.Conn)
}
// ServerCreator is a function to create proxy servers.

View File

@ -76,13 +76,14 @@ func NewSocks5Server(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe serves socks5 requests.
func (s *SOCKS5) ListenAndServe() {
func (s *SOCKS5) ListenAndServe(c net.Conn) {
go s.ListenAndServeUDP()
s.ListenAndServeTCP()
s.ListenAndServeTCP(c)
}
// ListenAndServeTCP .
func (s *SOCKS5) ListenAndServeTCP() {
func (s *SOCKS5) ListenAndServeTCP(c net.Conn) {
if c == nil {
l, err := net.Listen("tcp", s.addr)
if err != nil {
log.F("[socks5] failed to listen on %s: %v", s.addr, err)
@ -98,6 +99,9 @@ func (s *SOCKS5) ListenAndServeTCP() {
continue
}
go s.ServeTCP(c)
}
} else {
go s.ServeTCP(c)
}
}

View File

@ -66,13 +66,14 @@ func NewSSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe serves ss requests.
func (s *SS) ListenAndServe() {
func (s *SS) ListenAndServe(c net.Conn) {
go s.ListenAndServeUDP()
s.ListenAndServeTCP()
s.ListenAndServeTCP(c)
}
// ListenAndServeTCP serves tcp ss requests.
func (s *SS) ListenAndServeTCP() {
func (s *SS) ListenAndServeTCP(c net.Conn) {
if c == nil {
l, err := net.Listen("tcp", s.addr)
if err != nil {
log.F("[ss] failed to listen on %s: %v", s.addr, err)
@ -89,6 +90,9 @@ func (s *SS) ListenAndServeTCP() {
}
go s.ServeTCP(c)
}
} else {
go s.ServeTCP(c)
}
}
// ServeTCP serves tcp ss requests.

View File

@ -48,7 +48,7 @@ func NewTCPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe .
func (s *TCPTun) ListenAndServe() {
func (s *TCPTun) ListenAndServe(_ net.Conn) {
l, err := net.Listen("tcp", s.addr)
if err != nil {
log.F("failed to listen on %s: %v", s.addr, err)

View File

@ -3,6 +3,7 @@ package tls
import (
stdtls "crypto/tls"
"errors"
"fmt"
"net"
"net/url"
"strings"
@ -18,10 +19,17 @@ type TLS struct {
serverName string
skipVerify bool
certFile string
keyFile string
server proxy.Server
serverProto string
}
func init() {
proxy.RegisterDialer("tls", NewTLSDialer)
proxy.RegisterServer("tls", NewTLSTransport)
}
// NewTLS returns a tls proxy.
@ -48,6 +56,8 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) {
addr: addr,
serverName: serverName,
skipVerify: false,
certFile: "",
keyFile: "",
}
if skipVerify == "true" {
@ -57,6 +67,100 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) {
return p, nil
}
// NewTLSServerTransport returns a tls transport layer before the real server
func NewTLSTransport(s string, dialer proxy.Dialer) (proxy.Server, error) {
transport := strings.Split(s, ",")
// prepare transport listener
if len(transport) != 2 {
err := fmt.Errorf("malformd listener: %s", s)
log.F(err.Error())
return nil, err
}
u, err := url.Parse(transport[0])
if err != nil {
log.F("parse url err: %s", err)
return nil, err
}
// TODO: cert=&key=
query := u.Query()
certFile := query.Get("cert")
keyFile := query.Get("key")
addr := u.Host
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
serverName := addr[:colonPos]
p := &TLS{
dialer: dialer,
addr: addr,
serverName: serverName,
skipVerify: false,
certFile: certFile,
keyFile: keyFile,
serverProto: transport[1],
}
// prepare layer 7 server
p.server, err = proxy.ServerFromURL(transport[1], dialer)
return p, nil
}
func (s *TLS) ListenAndServe(c net.Conn) {
// c for TCP_FAST_OPEN
var tlsConfig *stdtls.Config
var ticketKey [32]byte
copy(ticketKey[:], "f8710951c1f6d0d95a95eed5e99b51f1")
if s.certFile != "" && s.keyFile != "" {
cert, err := stdtls.LoadX509KeyPair(s.certFile, s.keyFile)
if err != nil {
log.F("unabled load cert: %s, key %s", s.certFile, s.keyFile)
return
}
tlsConfig = &stdtls.Config{
Certificates: []stdtls.Certificate{cert},
MinVersion: stdtls.VersionTLS12,
MaxVersion: stdtls.VersionTLS13,
SessionTicketKey: ticketKey,
Accept0RTTData: true,
}
} else {
tlsConfig = nil
}
l, err := stdtls.Listen("tcp", s.addr, tlsConfig)
if err != nil {
log.F("failed to listen on tls %s: %v", s.addr, err)
return
}
defer l.Close()
log.F("listening TCP on %s with TLS", s.addr)
for {
c, err := l.Accept()
if err != nil {
log.F("[https] failed to accept: %v", err)
continue
}
// it's callee's response to decide process request in sync/async mode.
s.server.ListenAndServe(c)
}
}
// NewTLSDialer returns a tls proxy dialer.
func NewTLSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewTLS(s, dialer)
@ -79,6 +183,9 @@ func (s *TLS) Dial(network, addr string) (net.Conn, error) {
conf := &stdtls.Config{
ServerName: s.serverName,
InsecureSkipVerify: s.skipVerify,
ClientSessionCache: stdtls.NewLRUClientSessionCache(64),
MinVersion: stdtls.VersionTLS12,
MaxVersion: stdtls.VersionTLS13,
}
c := stdtls.Client(cc, conf)

View File

@ -51,7 +51,7 @@ func NewTProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe .
func (s *TProxy) ListenAndServe() {
func (s *TProxy) ListenAndServe(_ net.Conn) {
// go s.ListenAndServeTCP()
s.ListenAndServeUDP()
}

View File

@ -50,7 +50,7 @@ func NewUDPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe .
func (s *UDPTun) ListenAndServe() {
func (s *UDPTun) ListenAndServe(_ net.Conn) {
c, err := net.ListenPacket("udp", s.addr)
if err != nil {
log.F("[udptun] failed to listen on %s: %v", s.addr, err)

View File

@ -50,7 +50,7 @@ func NewUoTTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
}
// ListenAndServe .
func (s *UoTTun) ListenAndServe() {
func (s *UoTTun) ListenAndServe(_ net.Conn) {
c, err := net.ListenPacket("udp", s.addr)
if err != nil {
log.F("[uottun] failed to listen on %s: %v", s.addr, err)