tls, trojan: use 443 as default port if not specified

This commit is contained in:
nadoo 2020-10-07 21:06:49 +08:00
parent e7ebcbcde5
commit 8495f16a76
11 changed files with 91 additions and 127 deletions

View File

@ -53,7 +53,7 @@ we can set up local listeners as proxy servers, and forward requests to internet
|ssr | | |√| |client only
|ssh | | |√| |client only
|trojan | | |√|√|client only
|vless |√|√|√|√|client only
|vless |√|√|√|√|client & server
|vmess | | |√| |client only
|redir |√| | | |linux only
|redir6 |√| | | |linux only(ipv6)

5
go.mod
View File

@ -11,8 +11,9 @@ require (
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/xtaci/kcp-go/v5 v5.5.17
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d // indirect
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 // indirect
golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf // indirect
golang.org/x/tools v0.0.0-20201007032633-0806396f153e // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
)

12
go.sum
View File

@ -141,8 +141,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgN
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c h1:dk0ukUIHmGHqASjP0iue2261isepFCC6XRCSd1nHgDw=
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c/go.mod h1:iQL9McJNjoIa5mjH6nYTCTZXUN6RP+XW3eib7Ya3XcI=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -167,14 +167,18 @@ golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf h1:AvBTl0xbF/KtHyvm61X4gSPF7/dKJ/xQqJwKr1Qu9no=
golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d h1:vWQvJ/Z0Lu+9/8oQ/pAYXNzbc7CMnBl+tULGVHOy3oE=
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201007032633-0806396f153e h1:FJA2W4BQfMGZ+CD/tiAc39HXecuRsJl3EuczaSUu/Yk=
golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=

View File

@ -18,7 +18,7 @@ import (
)
var (
version = "0.11.1"
version = "0.11.2"
config = parseConfig()
)

View File

@ -4,7 +4,6 @@
package redir
import (
"errors"
"net"
"net/url"
"strings"
@ -13,14 +12,6 @@ import (
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/proxy"
"github.com/nadoo/glider/proxy/socks"
)
const (
// SO_ORIGINAL_DST from linux/include/uapi/linux/netfilter_ipv4.h
SO_ORIGINAL_DST = 80
// IP6T_SO_ORIGINAL_DST from linux/include/uapi/linux/netfilter_ipv6/ip6_tables.h
IP6T_SO_ORIGINAL_DST = 80
)
// RedirProxy struct.
@ -85,13 +76,16 @@ func (s *RedirProxy) ListenAndServe() {
}
// Serve serves connections.
func (s *RedirProxy) Serve(c net.Conn) {
defer c.Close()
func (s *RedirProxy) Serve(cc net.Conn) {
defer cc.Close()
if c, ok := c.(*net.TCPConn); ok {
c.SetKeepAlive(true)
c, ok := cc.(*net.TCPConn)
if !ok {
log.F("[redir] not a tcp connection, can not chain redir proxy")
return
}
c.SetKeepAlive(true)
tgt, err := getOrigDst(c, s.ipv6)
if err != nil {
log.F("[redir] failed to get target address: %v", err)
@ -123,61 +117,49 @@ func (s *RedirProxy) Serve(c net.Conn) {
}
// Get the original destination of a TCP connection.
func getOrigDst(conn net.Conn, ipv6 bool) (socks.Addr, error) {
c, ok := conn.(*net.TCPConn)
if !ok {
return nil, errors.New("only work with TCP connection")
}
f, err := c.File()
func getOrigDst(c *net.TCPConn, ipv6 bool) (*net.TCPAddr, error) {
rc, err := c.SyscallConn()
if err != nil {
return nil, err
}
defer f.Close()
fd := f.Fd()
// The File() call above puts both the original socket fd and the file fd in blocking mode.
// Set the file fd back to non-blocking mode and the original socket fd will become non-blocking as well.
// Otherwise blocking I/O will waste OS threads.
if err := syscall.SetNonblock(int(fd), true); err != nil {
return nil, err
}
if ipv6 {
return getorigdstIPv6(fd)
}
return getorigdst(fd)
var addr *net.TCPAddr
rc.Control(func(fd uintptr) {
if ipv6 {
addr, err = ipv6_getorigdst(fd)
} else {
addr, err = getorigdst(fd)
}
})
return addr, err
}
// Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
func getorigdst(fd uintptr) (socks.Addr, error) {
raw := syscall.RawSockaddrInet4{}
func getorigdst(fd uintptr) (*net.TCPAddr, error) {
const _SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv4.h
var raw syscall.RawSockaddrInet4
siz := unsafe.Sizeof(raw)
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, _SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
return nil, err
}
addr := make([]byte, 1+net.IPv4len+2)
addr[0] = socks.ATypIP4
copy(addr[1:1+net.IPv4len], raw.Addr[:])
port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian
addr[1+net.IPv4len], addr[1+net.IPv4len+1] = port[0], port[1]
return addr, nil
var addr net.TCPAddr
addr.IP = raw.Addr[:]
port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // raw.Port is big-endian
addr.Port = int(port[0])<<8 | int(port[1])
return &addr, nil
}
// Call ipv6_getorigdst() from linux/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
func getorigdstIPv6(fd uintptr) (socks.Addr, error) {
raw := syscall.RawSockaddrInet6{}
// NOTE: I haven't tried yet but it should work since Linux 3.8.
func ipv6_getorigdst(fd uintptr) (*net.TCPAddr, error) {
const _IP6T_SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv6/ip6_tables.h
var raw syscall.RawSockaddrInet6
siz := unsafe.Sizeof(raw)
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IPV6, _IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
return nil, err
}
addr := make([]byte, 1+net.IPv6len+2)
addr[0] = socks.ATypIP6
copy(addr[1:1+net.IPv6len], raw.Addr[:])
port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian
addr[1+net.IPv6len], addr[1+net.IPv6len+1] = port[0], port[1]
return addr, nil
var addr net.TCPAddr
addr.IP = raw.Addr[:]
port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // raw.Port is big-endian
addr.Port = int(port[0])<<8 | int(port[1])
return &addr, nil
}

View File

@ -5,8 +5,7 @@ import (
"unsafe"
)
// https://github.com/golang/go/blob/9e6b79a5dfb2f6fe4301ced956419a0da83bd025/src/syscall/syscall_linux_386.go#L196
const GETSOCKOPT = 15
const GETSOCKOPT = 15 // https://golang.org/src/syscall/syscall_linux_386.go#L183
func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) error {
var a [6]uintptr

View File

@ -4,7 +4,6 @@ package redir
import "syscall"
// GETSOCKOPT from syscall
const GETSOCKOPT = syscall.SYS_GETSOCKOPT
func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) error {

View File

@ -38,39 +38,27 @@ func init() {
func NewTLS(s string, d proxy.Dialer, p proxy.Proxy) (*TLS, error) {
u, err := url.Parse(s)
if err != nil {
log.F("parse url err: %s", err)
log.F("[tls] parse url err: %s", err)
return nil, err
}
addr := u.Host
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
serverName := addr[:colonPos]
query := u.Query()
skipVerify := query.Get("skipVerify")
certFile := query.Get("cert")
keyFile := query.Get("key")
if customServer := query.Get("serverName"); customServer != "" {
serverName = customServer
}
t := &TLS{
dialer: d,
proxy: p,
addr: addr,
serverName: serverName,
skipVerify: false,
certFile: certFile,
keyFile: keyFile,
addr: u.Host,
serverName: query.Get("serverName"),
skipVerify: query.Get("skipVerify") == "true",
certFile: query.Get("cert"),
keyFile: query.Get("key"),
}
if skipVerify == "true" {
t.skipVerify = true
if t.serverName == "" {
host, port, _ := net.SplitHostPort(t.addr)
if port == "" {
t.addr = net.JoinHostPort(t.addr, "443")
}
t.serverName = host
}
return t, nil

View File

@ -9,7 +9,6 @@ import (
"encoding/hex"
"net"
"net/url"
"strings"
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/pool"
@ -37,14 +36,25 @@ func init() {
func NewTrojan(s string, d proxy.Dialer, p proxy.Proxy) (*Trojan, error) {
u, err := url.Parse(s)
if err != nil {
log.F("[trojan] parse err: %s", err)
log.F("[trojan] parse url err: %s", err)
return nil, err
}
query := u.Query()
t := &Trojan{
dialer: d,
proxy: p,
addr: u.Host,
dialer: d,
proxy: p,
addr: u.Host,
skipVerify: query.Get("skipVerify") == "true",
serverName: query.Get("serverName"),
}
if t.serverName == "" {
host, port, _ := net.SplitHostPort(t.addr)
if port == "" {
t.addr = net.JoinHostPort(t.addr, "443")
}
t.serverName = host
}
// pass
@ -52,24 +62,12 @@ func NewTrojan(s string, d proxy.Dialer, p proxy.Proxy) (*Trojan, error) {
hash.Write([]byte(u.User.Username()))
hex.Encode(t.pass[:], hash.Sum(nil))
// serverName
colonPos := strings.LastIndex(t.addr, ":")
if colonPos == -1 {
colonPos = len(t.addr)
}
t.serverName = t.addr[:colonPos]
// skipVerify
if u.Query().Get("skipVerify") == "true" {
t.skipVerify = true
}
t.tlsConfig = &tls.Config{
ServerName: t.serverName,
InsecureSkipVerify: t.skipVerify,
NextProtos: []string{"http/1.1"},
ClientSessionCache: tls.NewLRUClientSessionCache(64),
MinVersion: tls.VersionTLS10,
MinVersion: tls.VersionTLS12,
}
return t, nil

View File

@ -117,7 +117,7 @@ func ReadAddrString(r io.Reader) (string, error) {
return AddrString(atyp, host, port), nil
}
// AddrString returns a addr string inf format "host:port".
// AddrString returns a addr string in format of "host:port".
func AddrString(atyp Atyp, addr Addr, port Port) string {
var host string

View File

@ -5,7 +5,6 @@ import (
"errors"
"net"
"net/url"
"strings"
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/proxy"
@ -39,26 +38,20 @@ func NewWS(s string, d proxy.Dialer) (*WS, error) {
addr = d.Addr()
}
host := u.Query().Get("host")
if host == "" {
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
host = addr[:colonPos]
}
client, err := NewClient(host, u.Path)
if err != nil {
log.F("[ws] create ws client error: %s", err)
return nil, err
}
p := &WS{
dialer: d,
addr: addr,
host: host,
client: client,
host: u.Query().Get("host"),
}
if p.host == "" {
p.host, _, _ = net.SplitHostPort(addr)
}
p.client, err = NewClient(p.host, u.Path)
if err != nil {
log.F("[ws] create ws client error: %s", err)
return nil, err
}
return p, nil