change "func GetProxy() Proxy" to "GetProxy(dstAddr string) Proxy" so we could add rule based proxy later

This commit is contained in:
nadoo 2017-07-29 23:20:27 +08:00
parent 88dda17725
commit bf692de636
9 changed files with 33 additions and 69 deletions

View File

@ -25,7 +25,6 @@ const MaxUDPDNSLen = 512
type dnstun struct { type dnstun struct {
*proxy *proxy
addr string
raddr string raddr string
} }
@ -33,7 +32,6 @@ type dnstun struct {
func DNSTunProxy(addr, raddr string, upProxy Proxy) (Proxy, error) { func DNSTunProxy(addr, raddr string, upProxy Proxy) (Proxy, error) {
s := &dnstun{ s := &dnstun{
proxy: newProxy(addr, upProxy), proxy: newProxy(addr, upProxy),
addr: addr,
raddr: raddr, raddr: raddr,
} }
@ -66,7 +64,7 @@ func (s *dnstun) ListenAndServe() {
// TODO: check domain rules and get a proper proxy. // TODO: check domain rules and get a proper proxy.
domain := getDomain(data) domain := getDomain(data)
rc, err := s.GetProxy().Dial("tcp", s.raddr) rc, err := s.GetProxy(s.raddr).Dial("tcp", s.raddr)
if err != nil { if err != nil {
logf("failed to connect to server %v: %v", s.raddr, err) logf("failed to connect to server %v: %v", s.raddr, err)
return return

View File

@ -19,14 +19,12 @@ import (
// httpproxy // httpproxy
type httpproxy struct { type httpproxy struct {
*proxy *proxy
addr string
} }
// HTTPProxy returns a http proxy. // HTTPProxy returns a http proxy.
func HTTPProxy(addr string, upProxy Proxy) (Proxy, error) { func HTTPProxy(addr string, upProxy Proxy) (Proxy, error) {
s := &httpproxy{ s := &httpproxy{
proxy: newProxy(addr, upProxy), proxy: newProxy(addr, upProxy),
addr: addr,
} }
return s, nil return s, nil
@ -94,7 +92,7 @@ func (s *httpproxy) Serve(c net.Conn) {
tgt += ":80" tgt += ":80"
} }
rc, err := s.GetProxy().Dial("tcp", tgt) rc, err := s.GetProxy(tgt).Dial("tcp", tgt)
if err != nil { if err != nil {
fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto) fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto)
logf("failed to dial: %v", err) logf("failed to dial: %v", err)
@ -150,7 +148,7 @@ func (s *httpproxy) Serve(c net.Conn) {
} }
func (s *httpproxy) servHTTPS(method, requestURI, proto string, c net.Conn) { func (s *httpproxy) servHTTPS(method, requestURI, proto string, c net.Conn) {
rc, err := s.GetProxy().Dial("tcp", requestURI) rc, err := s.GetProxy(requestURI).Dial("tcp", requestURI)
if err != nil { if err != nil {
c.Write([]byte(proto)) c.Write([]byte(proto))
c.Write([]byte(" 502 ERROR\r\n\r\n")) c.Write([]byte(" 502 ERROR\r\n\r\n"))
@ -173,7 +171,7 @@ func (s *httpproxy) servHTTPS(method, requestURI, proto string, c net.Conn) {
// Dial connects to the address addr on the network net via the proxy. // Dial connects to the address addr on the network net via the proxy.
func (s *httpproxy) Dial(network, addr string) (net.Conn, error) { func (s *httpproxy) Dial(network, addr string) (net.Conn, error) {
rc, err := s.GetProxy().Dial("tcp", s.addr) rc, err := s.GetProxy(s.addr).Dial("tcp", s.addr)
if err != nil { if err != nil {
logf("dial to %s error: %s", s.addr, err) logf("dial to %s error: %s", s.addr, err)
return nil, err return nil, err

View File

@ -43,13 +43,13 @@ func MixedProxy(network, addr, user, pass string, upProxy Proxy) (Proxy, error)
// mixedproxy . // mixedproxy .
func (p *mixedproxy) ListenAndServe() { func (p *mixedproxy) ListenAndServe() {
l, err := net.Listen("tcp", p.Addr()) l, err := net.Listen("tcp", p.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", p.Addr(), err) logf("failed to listen on %s: %v", p.addr, err)
return return
} }
logf("listening TCP on %s", p.Addr()) logf("listening TCP on %s", p.addr)
for { for {
c, err := l.Accept() c, err := l.Accept()

View File

@ -24,7 +24,7 @@ type Proxy interface {
CurrentProxy() Proxy CurrentProxy() Proxy
// Get a proxy according to the strategy // Get a proxy according to the strategy
GetProxy() Proxy GetProxy(dstAddr string) Proxy
// Switch to the next proxy // Switch to the next proxy
NextProxy() Proxy NextProxy() Proxy
@ -58,7 +58,7 @@ func newProxy(addr string, forward Proxy) *proxy {
func (p *proxy) ListenAndServe() { logf("base proxy ListenAndServe") } func (p *proxy) ListenAndServe() { logf("base proxy ListenAndServe") }
func (p *proxy) Serve(c net.Conn) { logf("base proxy Serve") } func (p *proxy) Serve(c net.Conn) { logf("base proxy Serve") }
func (p *proxy) CurrentProxy() Proxy { return p.forward } func (p *proxy) CurrentProxy() Proxy { return p.forward }
func (p *proxy) GetProxy() Proxy { return p.forward } func (p *proxy) GetProxy(dstAddr string) Proxy { return p.forward }
func (p *proxy) NextProxy() Proxy { return p.forward } func (p *proxy) NextProxy() Proxy { return p.forward }
func (p *proxy) Enabled() bool { return p.enabled } func (p *proxy) Enabled() bool { return p.enabled }
func (p *proxy) SetEnable(enable bool) { p.enabled = enable } func (p *proxy) SetEnable(enable bool) { p.enabled = enable }

View File

@ -4,7 +4,6 @@
package main package main
import ( import (
"errors"
"net" "net"
"syscall" "syscall"
"unsafe" "unsafe"
@ -56,7 +55,6 @@ func (s *redir) ListenAndServe() {
c.SetKeepAlive(true) c.SetKeepAlive(true)
} }
// tgt, c, err := getOriginalDstAddr(c)
tgt, err := getOrigDst(c, false) tgt, err := getOrigDst(c, false)
if err != nil { if err != nil {
logf("failed to get target address: %v", err) logf("failed to get target address: %v", err)
@ -84,34 +82,6 @@ func (s *redir) ListenAndServe() {
} }
} }
// 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()
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 ipv6_getorigdst(fd)
}
return getorigdst(fd)
}
// Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c // Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
func getorigdst(fd uintptr) (socks.Addr, error) { func getorigdst(fd uintptr) (socks.Addr, error) {
raw := syscall.RawSockaddrInet4{} raw := syscall.RawSockaddrInet4{}

View File

@ -57,8 +57,9 @@ var socks5Errors = []string{
type socks5 struct { type socks5 struct {
*proxy *proxy
network, addr string network string
user, password string user string
password string
} }
// SOCKS5Proxy returns a Proxy that makes SOCKSv5 connections to the given address // SOCKS5Proxy returns a Proxy that makes SOCKSv5 connections to the given address
@ -66,7 +67,6 @@ type socks5 struct {
func SOCKS5Proxy(network, addr, user, pass string, upProxy Proxy) (Proxy, error) { func SOCKS5Proxy(network, addr, user, pass string, upProxy Proxy) (Proxy, error) {
s := &socks5{ s := &socks5{
proxy: newProxy(addr, upProxy), proxy: newProxy(addr, upProxy),
addr: addr,
user: user, user: user,
password: pass, password: pass,
} }
@ -108,7 +108,7 @@ func (s *socks5) Serve(c net.Conn) {
return return
} }
rc, err := s.GetProxy().Dial("tcp", tgt.String()) rc, err := s.GetProxy(tgt.String()).Dial("tcp", tgt.String())
if err != nil { if err != nil {
logf("failed to connect to target: %v", err) logf("failed to connect to target: %v", err)
return return
@ -134,7 +134,7 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network) return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
} }
c, err := s.GetProxy().Dial(s.network, s.addr) c, err := s.GetProxy(s.addr).Dial(s.network, s.addr)
if err != nil { if err != nil {
logf("dial to %s error: %s", s.addr, err) logf("dial to %s error: %s", s.addr, err)
return nil, err return nil, err

12
ss.go
View File

@ -32,13 +32,13 @@ func SSProxy(addr, method, pass string, upProxy Proxy) (Proxy, error) {
// ListenAndServe shadowsocks requests as a server. // ListenAndServe shadowsocks requests as a server.
func (s *ss) ListenAndServe() { func (s *ss) ListenAndServe() {
l, err := net.Listen("tcp", s.Addr()) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", s.Addr(), err) logf("failed to listen on %s: %v", s.addr, err)
return return
} }
logf("listening TCP on %s", s.Addr()) logf("listening TCP on %s", s.addr)
for { for {
c, err := l.Accept() c, err := l.Accept()
@ -65,7 +65,7 @@ func (s *ss) Serve(c net.Conn) {
return return
} }
rc, err := s.GetProxy().Dial("tcp", tgt.String()) rc, err := s.GetProxy(tgt.String()).Dial("tcp", tgt.String())
if err != nil { if err != nil {
logf("failed to connect to target: %v", err) logf("failed to connect to target: %v", err)
return return
@ -92,9 +92,9 @@ func (s *ss) Dial(network, addr string) (net.Conn, error) {
return nil, errors.New("Unable to parse address: " + addr) return nil, errors.New("Unable to parse address: " + addr)
} }
c, err := s.GetProxy().Dial("tcp", s.Addr()) c, err := s.GetProxy(s.addr).Dial("tcp", s.addr)
if err != nil { if err != nil {
logf("dial to %s error: %s", s.Addr(), err) logf("dial to %s error: %s", s.addr, err)
return nil, err return nil, err
} }

View File

@ -49,7 +49,7 @@ func newRRProxy(addr string, forwarders []Proxy) Proxy {
func (p *rrProxy) ListenAndServe() {} func (p *rrProxy) ListenAndServe() {}
func (p *rrProxy) Serve(c net.Conn) {} func (p *rrProxy) Serve(c net.Conn) {}
func (p *rrProxy) CurrentProxy() Proxy { return p.forwarders[p.idx] } func (p *rrProxy) CurrentProxy() Proxy { return p.forwarders[p.idx] }
func (p *rrProxy) GetProxy() Proxy { return p.NextProxy() } func (p *rrProxy) GetProxy(dstAddr string) Proxy { return p.NextProxy() }
func (p *rrProxy) NextProxy() Proxy { func (p *rrProxy) NextProxy() Proxy {
n := len(p.forwarders) n := len(p.forwarders)
@ -91,7 +91,7 @@ func newHAProxy(addr string, forwarders []Proxy) Proxy {
return &haProxy{Proxy: newRRProxy(addr, forwarders)} return &haProxy{Proxy: newRRProxy(addr, forwarders)}
} }
func (p *haProxy) GetProxy() Proxy { func (p *haProxy) GetProxy(dstAddr string) Proxy {
proxy := p.CurrentProxy() proxy := p.CurrentProxy()
if proxy.Enabled() == false { if proxy.Enabled() == false {
return p.NextProxy() return p.NextProxy()

View File

@ -4,7 +4,6 @@ import "net"
type tcptun struct { type tcptun struct {
*proxy *proxy
addr string
raddr string raddr string
} }
@ -12,7 +11,6 @@ type tcptun struct {
func TCPTunProxy(addr, raddr string, upProxy Proxy) (Proxy, error) { func TCPTunProxy(addr, raddr string, upProxy Proxy) (Proxy, error) {
s := &tcptun{ s := &tcptun{
proxy: newProxy(addr, upProxy), proxy: newProxy(addr, upProxy),
addr: addr,
raddr: raddr, raddr: raddr,
} }
@ -43,7 +41,7 @@ func (s *tcptun) ListenAndServe() {
c.SetKeepAlive(true) c.SetKeepAlive(true)
} }
rc, err := s.GetProxy().Dial("tcp", s.raddr) rc, err := s.GetProxy(s.raddr).Dial("tcp", s.raddr)
if err != nil { if err != nil {
logf("failed to connect to target: %v", err) logf("failed to connect to target: %v", err)