From ba3546cacb06227453f7decaa3c3eba1e37b8f13 Mon Sep 17 00:00:00 2001 From: txthinking Date: Sat, 4 Jul 2020 16:21:59 +0800 Subject: [PATCH] $ brook hijackhttps --- OPENSOURCELICENSES | 28 -- cli/brook/main.go | 127 +------- hijackhttps.go | 24 +- plugin/middleman/blackwhite/blackwhite.go | 332 -------------------- plugin/middleman/blackwhite/test_test.go | 33 -- plugin/middleman/countryonly/countryonly.go | 317 ------------------- sysproxy/system_darwin.go | 106 ------- sysproxy/system_linux.go | 73 ----- sysproxy/system_other.go | 75 ----- sysproxy/system_windows.go | 222 ------------- tun.go | 154 --------- tun_darwin.go | 64 ---- tun_linux.go | 64 ---- tun_other.go | 50 --- tun_windows.go | 79 ----- 15 files changed, 13 insertions(+), 1735 deletions(-) delete mode 100644 plugin/middleman/blackwhite/blackwhite.go delete mode 100644 plugin/middleman/blackwhite/test_test.go delete mode 100644 plugin/middleman/countryonly/countryonly.go delete mode 100644 sysproxy/system_darwin.go delete mode 100644 sysproxy/system_linux.go delete mode 100644 sysproxy/system_other.go delete mode 100644 sysproxy/system_windows.go delete mode 100644 tun.go delete mode 100644 tun_darwin.go delete mode 100644 tun_linux.go delete mode 100644 tun_other.go delete mode 100644 tun_windows.go diff --git a/OPENSOURCELICENSES b/OPENSOURCELICENSES index d24279d0c..6b6d38f7b 100644 --- a/OPENSOURCELICENSES +++ b/OPENSOURCELICENSES @@ -167,34 +167,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -### gotun2socks - -https://github.com/yinghuocho/gotun2socks - -Copyright (c) 2016, yinghuocho -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ### minify https://github.com/tdewolff/minify diff --git a/cli/brook/main.go b/cli/brook/main.go index e296888b5..37d5fc86f 100644 --- a/cli/brook/main.go +++ b/cli/brook/main.go @@ -27,7 +27,6 @@ import ( _ "net/http/pprof" "github.com/txthinking/brook" - "github.com/txthinking/brook/sysproxy" "github.com/urfave/cli" ) @@ -472,93 +471,10 @@ func main() { }, &cli.Command{ Name: "tun", - Usage: "Run as tun, both TCP and UDP, [src <-> $ brook tun <-> $ brook server <-> dst], [works with $ brook server]", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "server", - Aliases: []string{"s"}, - Usage: "Brook server address, like: 1.2.3.4:1080", - }, - &cli.StringFlag{ - Name: "password", - Aliases: []string{"p"}, - Usage: "Brook server password", - }, - &cli.StringFlag{ - Name: "listen", - Aliases: []string{"l"}, - Usage: "Listen address, MUST contain IP, like: 127.0.0.1:1080", - }, - &cli.StringFlag{ - Name: "dns", - Value: "8.8.8.8", - Usage: "DNS Server, like: 8.8.8.8", - }, - &cli.IntFlag{ - Name: "tcpTimeout", - Value: 60, - Usage: "connection tcp keepalive timeout (s)", - }, - &cli.IntFlag{ - Name: "tcpDeadline", - Value: 0, - Usage: "connection deadline time (s)", - }, - &cli.IntFlag{ - Name: "udpDeadline", - Value: 60, - Usage: "connection deadline time (s)", - }, - &cli.IntFlag{ - Name: "udpSessionTime", - Value: 60, - Usage: "udp session time (s), in most cases need this", - }, - &cli.StringFlag{ - Name: "tunDevice", - Usage: "tun name", - Value: "tun0", - }, - &cli.StringFlag{ - Name: "tunIP", - Usage: "tun IP", - Value: "10.9.9.2", - }, - &cli.StringFlag{ - Name: "tunGateway", - Usage: "tun gateway", - Value: "10.9.9.1", - }, - &cli.StringFlag{ - Name: "tunMask", - Usage: "tun mask", - Value: "255.255.255.0", - }, - &cli.BoolFlag{ - Name: "letBrookDoAllForMe", - Usage: "See more: https://github.com/txthinking/brook/wiki/How-to-run-tun-on-Linux,-macOS-and-Windows", - }, - }, + Usage: "tun", + Flags: []cli.Flag{}, Action: func(c *cli.Context) error { - if c.String("listen") == "" || c.String("server") == "" || c.String("password") == "" { - cli.ShowCommandHelp(c, "tun") - return nil - } - if debug { - enableDebug() - } - s, err := brook.NewTun(c.String("listen"), c.String("server"), c.String("password"), c.String("dns"), c.Int("tcpTimeout"), c.Int("tcpDeadline"), c.Int("udpDeadline"), c.Int("udpSessionTime"), c.String("tunDevice"), c.String("tunIP"), c.String("tunGateway"), c.String("tunMask")) - if err != nil { - return err - } - s.LetBrookDoAllForMe = c.Bool("letBrookDoAllForMe") - go func() { - log.Println(s.ListenAndServe()) - }() - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - <-sigs - return s.Shutdown() + return errors.New("Deprecated, please try https://github.com/txthinking/ipio") }, }, &cli.Command{ @@ -988,7 +904,7 @@ func main() { Usage: "Socks5 password, optional", }, &cli.StringFlag{ - Name: "loopbackip", + Name: "listendnsip", Usage: "127.0.0.1 or ::1, will create a DNS server with it, and listen TCP 443 on it", Value: "127.0.0.1", }, @@ -1026,7 +942,7 @@ func main() { if debug { enableDebug() } - s, err := brook.NewHijackHTTPS(c.String("socks5"), c.String("socks5username"), c.String("socks5password"), c.String("loopbackip"), c.String("defaultDNSServer"), c.String("list"), c.Int("tcpTimeout"), c.Int("tcpDeadline"), c.Int("udpDeadline")) + s, err := brook.NewHijackHTTPS(c.String("socks5"), c.String("socks5username"), c.String("socks5password"), c.String("listendnsip"), c.String("defaultDNSServer"), c.String("list"), c.Int("tcpTimeout"), c.Int("tcpDeadline"), c.Int("udpDeadline")) if err != nil { return err } @@ -1096,38 +1012,6 @@ func main() { return p.ListenAndServe() }, }, - &cli.Command{ - Name: "systemproxy", - Usage: "Set system proxy with pac url, or remove, only works on macOS/Windows", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "url", - Aliases: []string{"u"}, - Usage: "Pac address: like: http://127.0.0.1/pac", - }, - &cli.BoolFlag{ - Name: "remove", - Aliases: []string{"r"}, - Usage: "Remove pac url from system proxy", - }, - }, - Action: func(c *cli.Context) error { - if !c.Bool("remove") && c.String("url") == "" { - cli.ShowCommandHelp(c, "systemproxy") - return nil - } - if c.Bool("remove") { - if err := sysproxy.TurnOffSystemProxy(); err != nil { - return err - } - return nil - } - if err := sysproxy.TurnOnSystemProxy(c.String("url")); err != nil { - return err - } - return nil - }, - }, &cli.Command{ Name: "ssserver", Usage: "Run as shadowsocks server, both TCP and UDP, fixed method is aes-256-cfb", @@ -1331,6 +1215,7 @@ func main() { fmt.Println("") fmt.Println("Nami:", "https://github.com/txthinking/nami") fmt.Println("Joker:", "https://github.com/txthinking/joker") + fmt.Println("Ipio:", "https://github.com/txthinking/ipio") fmt.Println("") return nil }, diff --git a/hijackhttps.go b/hijackhttps.go index 6e3b07ce6..aa852da3a 100644 --- a/hijackhttps.go +++ b/hijackhttps.go @@ -34,7 +34,7 @@ import ( // HijackHTTPS. type HijackHTTPS struct { Dial proxy.Dialer - LoopBackIP string + ListenDNSIP string DefaultDNS string Domains map[string]byte UDPDNSServer *dns.Server @@ -47,7 +47,7 @@ type HijackHTTPS struct { } // NewHijackHTTPS. -func NewHijackHTTPS(socks5addr, socks5username, socks5password, loopbackip, defaultDNS, list string, tcpTimeout, tcpDeadline, udpDeadline int) (*HijackHTTPS, error) { +func NewHijackHTTPS(socks5addr, socks5username, socks5password, listendnsip, defaultDNS, list string, tcpTimeout, tcpDeadline, udpDeadline int) (*HijackHTTPS, error) { ds := make(map[string]byte) if list != "" { ss, err := readList(list) @@ -85,7 +85,7 @@ func NewHijackHTTPS(socks5addr, socks5username, socks5password, loopbackip, defa } s := &HijackHTTPS{ Dial: dial, - LoopBackIP: loopbackip, + ListenDNSIP: listendnsip, DefaultDNS: defaultDNS, Domains: ds, TCPTimeout: tcpTimeout, @@ -98,13 +98,6 @@ func NewHijackHTTPS(socks5addr, socks5username, socks5password, loopbackip, defa // Run server. func (s *HijackHTTPS) ListenAndServe() error { - // l, err := sysproxy.GetDNSServers() - // if err != nil { - // return err - // } - // if err := sysproxy.SetDNSServers([]string{s.LoopBackIP}); err != nil { - // return err - // } s.RunnerGroup.Add(&runnergroup.Runner{ Start: func() error { return s.RunUDPDNSServer() @@ -141,15 +134,12 @@ func (s *HijackHTTPS) ListenAndServe() error { }, }) err := s.RunnerGroup.Wait() - // if err := sysproxy.SetDNSServers(l); err != nil { - // log.Println(err) - // } return err } func (s *HijackHTTPS) RunUDPDNSServer() error { s.UDPDNSServer = &dns.Server{ - Addr: net.JoinHostPort(s.LoopBackIP, "53"), + Addr: net.JoinHostPort(s.ListenDNSIP, "53"), Net: "udp", ReadTimeout: time.Duration(s.UDPDeadline) * time.Second, WriteTimeout: time.Duration(s.UDPDeadline) * time.Second, @@ -160,7 +150,7 @@ func (s *HijackHTTPS) RunUDPDNSServer() error { func (s *HijackHTTPS) RunTCPDNSServer() error { s.TCPDNSServer = &dns.Server{ - Addr: net.JoinHostPort(s.LoopBackIP, "53"), + Addr: net.JoinHostPort(s.ListenDNSIP, "53"), Net: "tcp", ReadTimeout: time.Duration(s.TCPTimeout) * time.Second, WriteTimeout: time.Duration(s.TCPTimeout) * time.Second, @@ -190,7 +180,7 @@ func (s *HijackHTTPS) DNSHandle(network string) dns.Handler { m.Authoritative = true m.Answer = append(m.Answer, &dns.A{ Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60}, - A: net.ParseIP(s.LoopBackIP), + A: net.ParseIP(s.ListenDNSIP), }) w.WriteMsg(m) return @@ -229,7 +219,7 @@ func (s *HijackHTTPS) DNSHandle(network string) dns.Handler { func (s *HijackHTTPS) RunHTTPSServer() error { var err error - s.HTTPSServer, err = net.Listen("tcp", net.JoinHostPort(s.LoopBackIP, "443")) + s.HTTPSServer, err = net.Listen("tcp", net.JoinHostPort(s.ListenDNSIP, "443")) if err != nil { return err } diff --git a/plugin/middleman/blackwhite/blackwhite.go b/plugin/middleman/blackwhite/blackwhite.go deleted file mode 100644 index 890b3d444..000000000 --- a/plugin/middleman/blackwhite/blackwhite.go +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package blackwhite - -import ( - "bytes" - "errors" - "io/ioutil" - "net" - "net/http" - "strings" - "time" - - "github.com/miekg/dns" - "github.com/txthinking/socks5" - "github.com/txthinking/x" -) - -var Dial x.Dialer = x.DefaultDial - -// BlackWhite is a middleman. -type BlackWhite struct { - Mode string // mode is white or black - Domains map[string]byte - Nets []*net.IPNet - Timeout int - Deadline int - Socks5Handle socks5.Handler - BlackDNS string - WhiteDNS string -} - -// NewBlackWhite returns a BlackWhite. -func NewBlackWhite(mode, domainURL, cidrURL, blackDNS, whiteDNS string, timeout, deadline int) (*BlackWhite, error) { - ds := make(map[string]byte) - ns := make([]*net.IPNet, 0) - if domainURL != "" { - data, err := readData(domainURL) - if err != nil { - return nil, err - } - data = bytes.TrimSpace(data) - data = bytes.Replace(data, []byte{0x20}, []byte{}, -1) - data = bytes.Replace(data, []byte{0x0d, 0x0a}, []byte{0x0a}, -1) - ss := strings.Split(string(data), "\n") - for _, v := range ss { - ds[v] = 0 - } - } - if cidrURL != "" { - data, err := readData(cidrURL) - if err != nil { - return nil, err - } - data = bytes.TrimSpace(data) - data = bytes.Replace(data, []byte{0x20}, []byte{}, -1) - data = bytes.Replace(data, []byte{0x0d, 0x0a}, []byte{0x0a}, -1) - ss := strings.Split(string(data), "\n") - ns = make([]*net.IPNet, 0, len(ss)) - for _, v := range ss { - _, in, err := net.ParseCIDR(v) - if err != nil { - return nil, err - } - ns = append(ns, in) - } - } - return &BlackWhite{ - Mode: mode, - Domains: ds, - Nets: ns, - Timeout: timeout, - Deadline: deadline, - Socks5Handle: &socks5.DefaultHandle{}, - WhiteDNS: whiteDNS, - BlackDNS: blackDNS, - }, nil -} - -// Has domain or IP. -func (b *BlackWhite) Has(host string) bool { - ip := net.ParseIP(host) - if ip != nil { - for _, v := range b.Nets { - if v.Contains(ip) { - return true - } - } - return false - } - ss := strings.Split(host, ".") - var s string - for i := len(ss) - 1; i >= 0; i-- { - if s == "" { - s = ss[i] - } else { - s = ss[i] + "." + s - } - if _, ok := b.Domains[s]; ok { - return true - } - } - return false -} - -// TCPHandle handles tcp request. -func (b *BlackWhite) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Request) (bool, error) { - // TODO dns - if r.Cmd == socks5.CmdConnect { - h, _, err := net.SplitHostPort(r.Address()) - if err != nil { - return false, err - } - if b.Mode == "white" && !b.Has(h) { - return false, nil - } - if b.Mode == "black" && b.Has(h) { - return false, nil - } - if err := b.Socks5Handle.TCPHandle(s, c, r); err != nil { - return true, err - } - return true, nil - } - return false, nil -} - -// UDPHandle handles udp packet. -func (b *BlackWhite) UDPHandle(s *socks5.Server, ca *net.UDPAddr, d *socks5.Datagram) (bool, error) { - if d.Address() == b.BlackDNS { - return b.DNSHandle(s, ca, d) - } - h, _, err := net.SplitHostPort(d.Address()) - if err != nil { - return false, err - } - if b.Mode == "white" && !b.Has(h) { - return false, nil - } - if b.Mode == "black" && b.Has(h) { - return false, nil - } - if err := b.Socks5Handle.UDPHandle(s, ca, d); err != nil { - return true, err - } - return true, nil -} - -// DNSHandle handles DNS query. -func (b *BlackWhite) DNSHandle(s *socks5.Server, addr *net.UDPAddr, d *socks5.Datagram) (bool, error) { - m := &dns.Msg{} - if err := m.Unpack(d.Data); err != nil { - return false, err - } - white := false - for _, v := range m.Question { - if len(v.Name) > 0 && b.Mode == "white" && b.Has(v.Name[0:len(v.Name)-1]) { - white = true - break - } - if len(v.Name) > 0 && b.Mode == "black" && !b.Has(v.Name[0:len(v.Name)-1]) { - white = true - break - } - } - if !white { - return false, nil - } - - conn, err := Dial.Dial("udp", b.WhiteDNS) - if err != nil { - return false, err - } - defer conn.Close() - co := &dns.Conn{Conn: conn} - if err := co.WriteMsg(m); err != nil { - return false, err - } - m1, err := co.ReadMsg() - if err != nil { - return false, err - } - // TODO rm - if m1.MsgHdr.Truncated { - conn, err := Dial.Dial("tcp", b.WhiteDNS) - if err != nil { - return false, err - } - defer conn.Close() - co := &dns.Conn{Conn: conn} - if err := co.WriteMsg(m); err != nil { - return false, err - } - m1, err = co.ReadMsg() - if err != nil { - return false, err - } - } - m1b, err := m1.Pack() - if err != nil { - return false, err - } - - a, ad, port, err := socks5.ParseAddress(addr.String()) - if err != nil { - return false, err - } - d = socks5.NewDatagram(a, ad, port, m1b) - if _, err := s.UDPConn.WriteToUDP(d.Bytes(), addr); err != nil { - return false, err - } - v, ok := s.TCPUDPAssociate.Get(addr.String()) - if ok { - ch := v.(chan byte) - ch <- 0x00 - s.TCPUDPAssociate.Delete(addr.String()) - } - return true, nil -} - -// Handle handles http proxy request, if the domain is in the white list. -func (b *BlackWhite) Handle(method, addr string, request []byte, conn *net.TCPConn) (handled bool, err error) { - h, _, err := net.SplitHostPort(addr) - if err != nil { - return false, err - } - if b.Mode == "white" && !b.Has(h) { - return false, nil - } - if b.Mode == "black" && b.Has(h) { - return false, nil - } - - tmp, err := Dial.Dial("tcp", addr) - if err != nil { - return false, err - } - rc := tmp.(*net.TCPConn) - defer rc.Close() - if b.Timeout != 0 { - if err := rc.SetKeepAlivePeriod(time.Duration(b.Timeout) * time.Second); err != nil { - return false, err - } - } - if b.Deadline != 0 { - if err := rc.SetDeadline(time.Now().Add(time.Duration(b.Deadline) * time.Second)); err != nil { - return false, err - } - } - if method == "CONNECT" { - _, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) - if err != nil { - return false, err - } - } - if method != "CONNECT" { - if _, err := rc.Write(request); err != nil { - return false, err - } - } - go func() { - var bf [1024 * 2]byte - for { - if b.Deadline != 0 { - if err := conn.SetDeadline(time.Now().Add(time.Duration(b.Deadline) * time.Second)); err != nil { - return - } - } - i, err := conn.Read(bf[:]) - if err != nil { - return - } - if _, err := rc.Write(bf[0:i]); err != nil { - return - } - } - }() - var bf [1024 * 2]byte - for { - if b.Deadline != 0 { - if err := rc.SetDeadline(time.Now().Add(time.Duration(b.Deadline) * time.Second)); err != nil { - return true, nil - } - } - i, err := rc.Read(bf[:]) - if err != nil { - return true, nil - } - if _, err := conn.Write(bf[0:i]); err != nil { - return true, nil - } - } - return true, nil -} - -func readData(url string) ([]byte, error) { - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - c := &http.Client{ - Timeout: 9 * time.Second, - } - r, err := c.Get(url) - if err != nil { - return nil, err - } - defer r.Body.Close() - data, err := ioutil.ReadAll(r.Body) - if err != nil { - return nil, err - } - return data, nil - } - if strings.HasPrefix(url, "file://") { - data, err := ioutil.ReadFile(url) - if err != nil { - return nil, err - } - return data, nil - } - return nil, errors.New("Unsupport URL") -} diff --git a/plugin/middleman/blackwhite/test_test.go b/plugin/middleman/blackwhite/test_test.go deleted file mode 100644 index a5a3f669d..000000000 --- a/plugin/middleman/blackwhite/test_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package blackwhite - -import ( - "log" - "testing" -) - -func TestTest(t *testing.T) { - bw, err := NewBlackWhite("white", "https://blackwhite.txthinking.com/white.list", "https://blackwhite.txthinking.com/white_cidr.list", "8.8.8.8:53", "119.29.29.29:53", 0, 6) - if err != nil { - log.Println(err) - return - } - log.Println(bw.Has("www.baidu.com")) - log.Println(bw.Has("39.156.69.79")) - log.Println(bw.Has("220.181.38.148")) - log.Println(bw.Has("119.29.29.29")) - log.Println(bw.Has("61.135.186.217")) -} diff --git a/plugin/middleman/countryonly/countryonly.go b/plugin/middleman/countryonly/countryonly.go deleted file mode 100644 index 524ba44f7..000000000 --- a/plugin/middleman/countryonly/countryonly.go +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package countryonly - -import ( - "bytes" - "errors" - "io/ioutil" - "net" - "net/http" - "strings" - "time" - - "github.com/miekg/dns" - "github.com/txthinking/socks5" - "github.com/txthinking/x" -) - -var Dial x.Dialer = x.DefaultDial - -// CountryOnly is a middleman. -type CountryOnly struct { - Domains map[string]byte - Nets []*net.IPNet - Timeout int - Deadline int - Socks5Handle socks5.Handler - InboundDNS string - CountryDNS string -} - -// NewCountryOnly returns a CountryOnly. -func NewCountryOnly(domainURL, cidrURL, inboundDNS, countryDNS string, timeout, deadline int) (*CountryOnly, error) { - ds := make(map[string]byte) - ns := make([]*net.IPNet, 0) - if domainURL != "" { - data, err := readData(domainURL) - if err != nil { - return nil, err - } - data = bytes.TrimSpace(data) - data = bytes.Replace(data, []byte{0x20}, []byte{}, -1) - data = bytes.Replace(data, []byte{0x0d, 0x0a}, []byte{0x0a}, -1) - ss := strings.Split(string(data), "\n") - for _, v := range ss { - ds[v] = 0 - } - } - if cidrURL != "" { - data, err := readData(cidrURL) - if err != nil { - return nil, err - } - data = bytes.TrimSpace(data) - data = bytes.Replace(data, []byte{0x20}, []byte{}, -1) - data = bytes.Replace(data, []byte{0x0d, 0x0a}, []byte{0x0a}, -1) - ss := strings.Split(string(data), "\n") - ns = make([]*net.IPNet, 0, len(ss)) - for _, v := range ss { - _, in, err := net.ParseCIDR(v) - if err != nil { - return nil, err - } - ns = append(ns, in) - } - } - return &CountryOnly{ - Domains: ds, - Nets: ns, - Timeout: timeout, - Deadline: deadline, - Socks5Handle: &socks5.DefaultHandle{}, - InboundDNS: inboundDNS, - CountryDNS: countryDNS, - }, nil -} - -// Has domain or IP. -func (b *CountryOnly) Has(host string) bool { - ip := net.ParseIP(host) - if ip != nil { - for _, v := range b.Nets { - if v.Contains(ip) { - return true - } - } - return false - } - ss := strings.Split(host, ".") - var s string - for i := len(ss) - 1; i >= 0; i-- { - if s == "" { - s = ss[i] - } else { - s = ss[i] + "." + s - } - if _, ok := b.Domains[s]; ok { - return true - } - } - return false -} - -// TCPHandle handles tcp request. -func (b *CountryOnly) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Request) (bool, error) { - // TODO dns - if r.Cmd == socks5.CmdConnect { - h, _, err := net.SplitHostPort(r.Address()) - if err != nil { - return false, err - } - if b.Has(h) { - return false, nil - } - if err := b.Socks5Handle.TCPHandle(s, c, r); err != nil { - return true, err - } - return true, nil - } - return false, nil -} - -// UDPHandle handles udp packet. -func (b *CountryOnly) UDPHandle(s *socks5.Server, ca *net.UDPAddr, d *socks5.Datagram) (bool, error) { - if d.Address() == b.InboundDNS { - return b.DNSHandle(s, ca, d) - } - h, _, err := net.SplitHostPort(d.Address()) - if err != nil { - return false, err - } - if b.Has(h) { - return false, nil - } - if err := b.Socks5Handle.UDPHandle(s, ca, d); err != nil { - return true, err - } - return true, nil -} - -// DNSHandle handles DNS query. -func (b *CountryOnly) DNSHandle(s *socks5.Server, addr *net.UDPAddr, d *socks5.Datagram) (bool, error) { - m := &dns.Msg{} - if err := m.Unpack(d.Data); err != nil { - return false, err - } - has := false - for _, v := range m.Question { - if len(v.Name) > 0 && b.Has(v.Name[0:len(v.Name)-1]) { - has = true - break - } - } - if has { - return false, nil - } - - conn, err := Dial.Dial("udp", b.CountryDNS) - if err != nil { - return false, err - } - defer conn.Close() - co := &dns.Conn{Conn: conn} - if err := co.WriteMsg(m); err != nil { - return false, err - } - m1, err := co.ReadMsg() - if err != nil { - return false, err - } - // TODO rm - if m1.MsgHdr.Truncated { - conn, err := Dial.Dial("tcp", b.CountryDNS) - if err != nil { - return false, err - } - defer conn.Close() - co := &dns.Conn{Conn: conn} - if err := co.WriteMsg(m); err != nil { - return false, err - } - m1, err = co.ReadMsg() - if err != nil { - return false, err - } - } - m1b, err := m1.Pack() - if err != nil { - return false, err - } - - a, ad, port, err := socks5.ParseAddress(addr.String()) - if err != nil { - return false, err - } - d = socks5.NewDatagram(a, ad, port, m1b) - if _, err := s.UDPConn.WriteToUDP(d.Bytes(), addr); err != nil { - return false, err - } - v, ok := s.TCPUDPAssociate.Get(addr.String()) - if ok { - ch := v.(chan byte) - ch <- 0x00 - s.TCPUDPAssociate.Delete(addr.String()) - } - return true, nil -} - -// Handle handles http proxy request, if the domain is in the white list. -func (b *CountryOnly) Handle(method, addr string, request []byte, conn *net.TCPConn) (handled bool, err error) { - h, _, err := net.SplitHostPort(addr) - if err != nil { - return false, err - } - if b.Has(h) { - return false, nil - } - - tmp, err := Dial.Dial("tcp", addr) - if err != nil { - return false, err - } - rc := tmp.(*net.TCPConn) - defer rc.Close() - if b.Timeout != 0 { - if err := rc.SetKeepAlivePeriod(time.Duration(b.Timeout) * time.Second); err != nil { - return false, err - } - } - if b.Deadline != 0 { - if err := rc.SetDeadline(time.Now().Add(time.Duration(b.Deadline) * time.Second)); err != nil { - return false, err - } - } - if method == "CONNECT" { - _, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) - if err != nil { - return false, err - } - } - if method != "CONNECT" { - if _, err := rc.Write(request); err != nil { - return false, err - } - } - go func() { - var bf [1024 * 2]byte - for { - if b.Deadline != 0 { - if err := conn.SetDeadline(time.Now().Add(time.Duration(b.Deadline) * time.Second)); err != nil { - return - } - } - i, err := conn.Read(bf[:]) - if err != nil { - return - } - if _, err := rc.Write(bf[0:i]); err != nil { - return - } - } - }() - var bf [1024 * 2]byte - for { - if b.Deadline != 0 { - if err := rc.SetDeadline(time.Now().Add(time.Duration(b.Deadline) * time.Second)); err != nil { - return true, nil - } - } - i, err := rc.Read(bf[:]) - if err != nil { - return true, nil - } - if _, err := conn.Write(bf[0:i]); err != nil { - return true, nil - } - } - return true, nil -} - -func readData(url string) ([]byte, error) { - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - c := &http.Client{ - Timeout: 9 * time.Second, - } - r, err := c.Get(url) - if err != nil { - return nil, err - } - defer r.Body.Close() - data, err := ioutil.ReadAll(r.Body) - if err != nil { - return nil, err - } - return data, nil - } - if strings.HasPrefix(url, "file://") { - data, err := ioutil.ReadFile(url) - if err != nil { - return nil, err - } - return data, nil - } - return nil, errors.New("Unsupport URL") -} diff --git a/sysproxy/system_darwin.go b/sysproxy/system_darwin.go deleted file mode 100644 index dbcbd8291..000000000 --- a/sysproxy/system_darwin.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package sysproxy - -import ( - "errors" - "os/exec" - "strings" -) - -// GetNetworkInterface returns default interface name, not dev name. -func GetNetworkInterface() (string, error) { - c := exec.Command("sh", "-c", "networksetup -listnetworkserviceorder | grep -B 1 $(route -n get default | grep interface | awk '{print $2}') | head -n 1 | sed 's/.*) //'") - out, err := c.CombinedOutput() - if err != nil { - return "", errors.New(string(out) + err.Error()) - } - return strings.TrimSpace(string(out)), nil -} - -// GetDefaultGateway returns default gateway. -func GetDefaultGateway() (string, error) { - c := exec.Command("sh", "-c", "route -n get default | grep gateway | awk '{print $2}'") - out, err := c.CombinedOutput() - if err != nil { - return "", errors.New(string(out) + err.Error()) - } - return strings.TrimSpace(string(out)), nil -} - -// GetDNSServers used to get DNS servers. -func GetDNSServers() ([]string, error) { - s, err := GetNetworkInterface() - if err != nil { - return nil, err - } - c := exec.Command("networksetup", "-getdnsservers", s) - out, err := c.CombinedOutput() - if err != nil { - return nil, errors.New(string(out) + err.Error()) - } - if strings.Contains(string(out), "aren't") { - return []string{}, nil - } - return strings.Split(strings.TrimSpace(string(out)), "\n"), nil -} - -// SetDNSServers used to set DNS servers. -func SetDNSServers(servers []string) error { - s, err := GetNetworkInterface() - if err != nil { - return err - } - if len(servers) != 0 { - servers = append([]string{"-setdnsservers", s}, servers...) - } else { - servers = []string{"-setdnsservers", s, "empty"} - } - c := exec.Command("networksetup", servers...) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} - -// TurnOnSystemProxy used to enable system pac proxy, pac is a URL. -func TurnOnSystemProxy(pac string) error { - s, err := GetNetworkInterface() - if err != nil { - return err - } - c := exec.Command("networksetup", "-setautoproxyurl", s, pac) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("networksetup", "-setautoproxystate", s, "on") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} - -// TurnOffSystemProxy used to disable system pac proxy. -func TurnOffSystemProxy() error { - s, err := GetNetworkInterface() - if err != nil { - return err - } - c := exec.Command("networksetup", "-setautoproxystate", s, "off") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} diff --git a/sysproxy/system_linux.go b/sysproxy/system_linux.go deleted file mode 100644 index 4baaf3fda..000000000 --- a/sysproxy/system_linux.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package sysproxy - -import ( - "errors" - "os" - "os/exec" - "strings" -) - -// GetNetworkInterface returns default interface dev name. -func GetNetworkInterface() (string, error) { - return "", nil -} - -// GetDefaultGateway returns default gateway. -func GetDefaultGateway() (string, error) { - c := exec.Command("sh", "-c", "ip route | grep default | awk '{print $3}'") - out, err := c.CombinedOutput() - if err != nil { - return "", errors.New(string(out) + err.Error()) - } - return strings.TrimSpace(string(out)), nil -} - -// GetDNSServers used to get DNS servers. -func GetDNSServers() ([]string, error) { - c := exec.Command("sh", "-c", "cat /etc/resolv.conf | grep -Pv \"^#\" | grep nameserver | awk '{print $2}'") - out, err := c.CombinedOutput() - if err != nil { - return nil, errors.New(string(out) + err.Error()) - } - if strings.TrimSpace(string(out)) == "" { - return []string{}, nil - } - return strings.Split(strings.TrimSpace(string(out)), "\n"), nil -} - -// SetDNSServers used to set system DNS servers. -func SetDNSServers(servers []string) error { - f, err := os.OpenFile("/etc/resolv.conf", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) - if err != nil { - return err - } - defer f.Close() - for _, v := range servers { - if _, err := f.WriteString("nameserver " + v + "\n"); err != nil { - return err - } - } - return nil -} - -func TurnOnSystemProxy(pac string) error { - return nil -} - -func TurnOffSystemProxy() error { - return nil -} diff --git a/sysproxy/system_other.go b/sysproxy/system_other.go deleted file mode 100644 index 9fb589405..000000000 --- a/sysproxy/system_other.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// +build !linux,!darwin,!windows - -package sysproxy - -import ( - "errors" - "os" - "os/exec" - "strings" -) - -// GetNetworkInterface returns default interface dev name. -func GetNetworkInterface() (string, error) { - return "", nil -} - -// GetDefaultGateway returns default gateway. -func GetDefaultGateway() (string, error) { - c := exec.Command("sh", "-c", "ip route | grep default | awk '{print $3}'") - out, err := c.CombinedOutput() - if err != nil { - return "", errors.New(string(out) + err.Error()) - } - return strings.TrimSpace(string(out)), nil -} - -// GetDNSServers used to get DNS servers. -func GetDNSServers() ([]string, error) { - c := exec.Command("sh", "-c", "cat /etc/resolv.conf | grep -Pv \"^#\" | grep nameserver | awk '{print $2}'") - out, err := c.CombinedOutput() - if err != nil { - return nil, errors.New(string(out) + err.Error()) - } - if strings.TrimSpace(string(out)) == "" { - return []string{}, nil - } - return strings.Split(strings.TrimSpace(string(out)), "\n"), nil -} - -// SetDNSServers used to set system DNS servers. -func SetDNSServers(servers []string) error { - f, err := os.OpenFile("/etc/resolv.conf", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) - if err != nil { - return err - } - defer f.Close() - for _, v := range servers { - if _, err := f.WriteString("nameserver " + v + "\n"); err != nil { - return err - } - } - return nil -} - -func TurnOnSystemProxy(pac string) error { - return nil -} - -func TurnOffSystemProxy() error { - return nil -} diff --git a/sysproxy/system_windows.go b/sysproxy/system_windows.go deleted file mode 100644 index 797ec01bc..000000000 --- a/sysproxy/system_windows.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package sysproxy - -import ( - "bytes" - "errors" - "os/exec" - "strings" - "syscall" -) - -// GetNetworkInterface returns interface name. -func GetNetworkInterface() (string, error) { - c := exec.Command("chcp", "65001") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return "", errors.New(string(out) + err.Error()) - } - c = exec.Command("netsh", "interface", "ip", "show", "address") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - out, err := c.CombinedOutput() - if err != nil { - return "", errors.New(string(out) + err.Error()) - } - l := strings.Split(string(out), "\n") - for i, v := range l { - if !strings.Contains(v, "Default Gateway") { - continue - } - l1 := strings.Split(v, "Gateway:") - if len(l1) != 2 { - continue - } - for j := i - 1; j >= 0; j-- { - if !strings.Contains(l[j], "Configuration for interface") { - continue - } - l1 := strings.Split(l[j], "\"") - if len(l1) != 3 { - return "", errors.New("Can't find network interface") - } - return strings.TrimSpace(l1[1]), nil - } - return "", errors.New("Can't find network interface") - } - return "", errors.New("Can't find network interface") -} - -// GetDefaultGateway returns default gateway. -func GetDefaultGateway() (string, error) { - c := exec.Command("chcp", "65001") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return "", errors.New(string(out) + err.Error()) - } - c = exec.Command("netsh", "interface", "ip", "show", "address") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - out, err := c.CombinedOutput() - if err != nil { - return "", errors.New(string(out) + err.Error()) - } - l := strings.Split(string(out), "\n") - for _, v := range l { - if !strings.Contains(v, "Default Gateway") { - continue - } - l1 := strings.Split(v, "Gateway:") - if len(l1) != 2 { - continue - } - if strings.TrimSpace(l1[1]) == "" { - continue - } - return strings.TrimSpace(l1[1]), nil - } - return "", errors.New("Can't find default gateway") -} - -// GetDNSServers used to get DNS servers. -func GetDNSServers() ([]string, error) { - s, err := GetNetworkInterface() - if err != nil { - return nil, err - } - c := exec.Command("netsh", "interface", "ip", "show", "dnsservers", s) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - out, err := c.CombinedOutput() - if err != nil { - return nil, errors.New(string(out) + err.Error()) - } - if !strings.Contains(string(out), "Statically Configured DNS Servers:") { - return []string{}, nil - } - l := strings.Split(string(out), "Statically Configured DNS Servers:") - if len(l) != 2 { - return nil, errors.New("Can't find dns servers") - } - l = strings.Split(l[1], "Register with which suffix:") - if len(l) != 2 { - return nil, errors.New("Can't find dns servers") - } - l = strings.Split(strings.TrimSpace(l[0]), "\n") - l = []string{} - for _, v := range l { - l = append(l, strings.TrimSpace(v)) - } - return l, nil -} - -// SetDNSServers used to set system DNS server. -func SetDNSServers(servers []string) error { - s, err := GetNetworkInterface() - if err != nil { - return err - } - if len(servers) == 0 { - c := exec.Command("netsh", "interface", "ip", "set", "dnsservers", s, "static", "none") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil - } - for i, v := range servers { - if i == 0 { - c := exec.Command("netsh", "interface", "ip", "set", "dnsservers", s, "static", v, "primary") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - continue - } - c := exec.Command("netsh", "interface", "ip", "add", "dnsservers", s, v) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - } - return nil -} - -// TurnOnSystemProxy used to enable system pac proxy, pac is a URL. -func TurnOnSystemProxy(pac string) error { - c := exec.Command("chcp", "65001") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command(`reg`, `add`, `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, `/v`, `AutoConfigURL`, `/t`, `REG_SZ`, `/d`, pac, `/f`) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command(`reg`, `add`, `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, `/v`, `ProxyEnable`, `/t`, `REG_DWORD`, `/d`, `0`, `/f`) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - if err := reloadWinProxy(); err != nil { - return err - } - return nil -} - -// TurnOffSystemProxy used to disable system pac proxy. -func TurnOffSystemProxy() error { - c := exec.Command("chcp", "65001") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command(`reg`, `query`, `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings`) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - out, err := c.CombinedOutput() - if err != nil { - return errors.New(string(out) + err.Error()) - } - if bytes.Contains(bytes.ToLower(out), []byte("autoconfigurl")) { - c := exec.Command(`reg`, `delete`, `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, `/v`, `AutoConfigURL`, `/f`) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - } - if err := reloadWinProxy(); err != nil { - return err - } - return nil -} - -func reloadWinProxy() error { - h, err := syscall.LoadLibrary("wininet.dll") - if err != nil { - return err - } - f, err := syscall.GetProcAddress(h, "InternetSetOptionW") - if err != nil { - return err - } - ret, _, errno := syscall.Syscall6(uintptr(f), 4, 0, 39, 0, 0, 0, 0) - if ret != 1 { - return errors.New(errno.Error()) - } - ret, _, errno = syscall.Syscall6(uintptr(f), 4, 0, 37, 0, 0, 0, 0) - if ret != 1 { - return errors.New(errno.Error()) - } - return nil -} diff --git a/tun.go b/tun.go deleted file mode 100644 index eda8dd0ff..000000000 --- a/tun.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// +build linux darwin windows - -package brook - -import ( - "errors" - "log" - "net" - - "github.com/txthinking/brook/limits" - "github.com/txthinking/brook/sysproxy" - "github.com/txthinking/gotun2socks" - "github.com/txthinking/gotun2socks/tun" - "github.com/txthinking/runnergroup" -) - -// Tun. -type Tun struct { - Client *Client - Tunnel *Tunnel - Tun *gotun2socks.Tun2Socks - ServerIP string - TunGateway string - OriginalDNSServers []string - RunnerGroup *runnergroup.RunnerGroup - LetBrookDoAllForMe bool -} - -// NewTun. -func NewTun(addr, server, password, dns string, tcpTimeout, tcpDeadline, udpDeadline, udpSessionTime int, tunDevice, tunIP, tunGateway, tunMask string) (*Tun, error) { - h, _, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } - if h != "127.0.0.1" { - return nil, errors.New("Must listen on 127.0.0.1") - } - h, p, err := net.SplitHostPort(server) - if err != nil { - return nil, err - } - l, err := net.LookupIP(h) - if err != nil { - return nil, err - } - if len(l) == 0 { - return nil, errors.New("Can not find server IP") - } - s := l[0].String() - server = net.JoinHostPort(s, p) - - c, err := NewClient(addr, "127.0.0.1", server, password, tcpTimeout, tcpDeadline, udpDeadline, udpSessionTime) - if err != nil { - return nil, err - } - dnsserver := net.JoinHostPort(dns, "53") - tl, err := NewTunnel("127.0.0.1:53", dnsserver, server, password, tcpTimeout, tcpDeadline, udpDeadline) - if err != nil { - return nil, err - } - f, err := tun.OpenTunDevice(tunDevice, tunIP, tunGateway, tunMask, []string{dns}) - if err != nil { - return nil, err - } - t := gotun2socks.New(f, addr, []string{dns}, false, true) - if err := limits.Raise(); err != nil { - log.Println("Try to raise system limits, got", err) - } - return &Tun{ - Client: c, - Tunnel: tl, - Tun: t, - ServerIP: s, - TunGateway: tunGateway, - RunnerGroup: runnergroup.New(), - }, nil -} - -// ListenAndServe starts to run Tun. -func (v *Tun) ListenAndServe() error { - if v.LetBrookDoAllForMe { - ds, err := sysproxy.GetDNSServers() - if err != nil { - return err - } - v.OriginalDNSServers = ds - - if err := sysproxy.SetDNSServers([]string{"127.0.0.1"}); err != nil { - return err - } - if err := v.AddRoutes(); err != nil { - return err - } - } - - v.RunnerGroup.Add(&runnergroup.Runner{ - Start: func() error { - return v.Client.ListenAndServe() - }, - Stop: func() error { - return v.Client.Shutdown() - }, - }) - v.RunnerGroup.Add(&runnergroup.Runner{ - Start: func() error { - return v.Tunnel.ListenAndServe() - }, - Stop: func() error { - return v.Tunnel.Shutdown() - }, - }) - ch := make(chan byte) - v.RunnerGroup.Add(&runnergroup.Runner{ - Start: func() error { - go v.Tun.Run() - <-ch - return nil - }, - Stop: func() error { - go v.Tun.Stop() - ch <- 0x00 - return nil - }, - }) - err := v.RunnerGroup.Wait() - if v.LetBrookDoAllForMe { - if err := sysproxy.SetDNSServers(v.OriginalDNSServers); err != nil { - log.Println(err) - } - if err := v.DeleteRoutes(); err != nil { - log.Println(err) - } - } - return err -} - -// Shutdown stops Tun. -func (v *Tun) Shutdown() error { - return v.RunnerGroup.Done() -} diff --git a/tun_darwin.go b/tun_darwin.go deleted file mode 100644 index d90a20f70..000000000 --- a/tun_darwin.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package brook - -import ( - "errors" - "os/exec" - - "github.com/txthinking/brook/sysproxy" -) - -// AddRoutes adds routes. -func (v *Tun) AddRoutes() error { - c := exec.Command("route", "add", "-net", "0.0.0.0", v.TunGateway, "-netmask", "128.0.0.0") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("route", "add", "-net", "128.0.0.0", v.TunGateway, "-netmask", "128.0.0.0") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - gw, err := sysproxy.GetDefaultGateway() - if err != nil { - return err - } - c = exec.Command("route", "add", "-host", v.ServerIP, gw, "-netmask", "255.255.255.255") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} - -// DeleteRoutes deletes routes. -func (v *Tun) DeleteRoutes() error { - c := exec.Command("route", "delete", "-net", "0.0.0.0", v.TunGateway, "-netmask", "128.0.0.0") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("route", "delete", "-net", "128.0.0.0", v.TunGateway, "-netmask", "128.0.0.0") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - gw, err := sysproxy.GetDefaultGateway() - if err != nil { - return err - } - c = exec.Command("route", "delete", "-host", v.ServerIP, gw, "-netmask", "255.255.255.255") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} diff --git a/tun_linux.go b/tun_linux.go deleted file mode 100644 index d15d7e17c..000000000 --- a/tun_linux.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package brook - -import ( - "errors" - "os/exec" - - "github.com/txthinking/brook/sysproxy" -) - -// AddRoutes adds routes. -func (v *Tun) AddRoutes() error { - c := exec.Command("ip", "route", "add", "0.0.0.0/1", "via", v.TunGateway) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("ip", "route", "add", "128.0.0.0/1", "via", v.TunGateway) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - gw, err := sysproxy.GetDefaultGateway() - if err != nil { - return err - } - c = exec.Command("ip", "route", "add", v.ServerIP, "via", gw) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} - -// DeleteRoutes deletes routes. -func (v *Tun) DeleteRoutes() error { - c := exec.Command("ip", "route", "del", "0.0.0.0/1", "via", v.TunGateway) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("ip", "route", "del", "128.0.0.0/1", "via", v.TunGateway) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - gw, err := sysproxy.GetDefaultGateway() - if err != nil { - return err - } - c = exec.Command("ip", "route", "del", v.ServerIP, "via", gw) - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} diff --git a/tun_other.go b/tun_other.go deleted file mode 100644 index a27a5894d..000000000 --- a/tun_other.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// +build !linux,!darwin,!windows - -package brook - -import ( - "errors" - - "github.com/txthinking/gotun2socks" - "github.com/txthinking/runnergroup" -) - -// Tun. -type Tun struct { - Client *Client - Tunnel *Tunnel - Tun *gotun2socks.Tun2Socks - ServerIP string - TunGateway string - OriginalDNSServers []string - RunnerGroup *runnergroup.RunnerGroup -} - -// NewTun. -func NewTun(addr, server, password, dns string, tcpTimeout, tcpDeadline, udpDeadline, udpSessionTime int, tunDevice, tunIP, tunGateway, tunMask string) (*Tun, error) { - return nil, errors.New("Unsupport your OS yet") -} - -// ListenAndServe starts to run Tun. -func (v *Tun) ListenAndServe() error { - return nil -} - -// Shutdown stops Tun. -func (v *Tun) Shutdown() error { - return nil -} diff --git a/tun_windows.go b/tun_windows.go deleted file mode 100644 index 79b679b57..000000000 --- a/tun_windows.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2016-present Cloud -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 3 of the GNU General Public -// License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package brook - -import ( - "errors" - "os/exec" - "syscall" - - "github.com/txthinking/brook/sysproxy" -) - -// AddRoutes adds routes. -func (v *Tun) AddRoutes() error { - c := exec.Command("chcp", "65001") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("route", "add", "0.0.0.0", "mask", "128.0.0.0", v.TunGateway) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("route", "add", "128.0.0.0", "mask", "128.0.0.0", v.TunGateway) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - gw, err := sysproxy.GetDefaultGateway() - if err != nil { - return err - } - c = exec.Command("route", "add", v.ServerIP, "mask", "255.255.255.255", gw, "metric", "1") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -} - -// DeleteRoutes deletes routes. -func (v *Tun) DeleteRoutes() error { - c := exec.Command("chcp", "65001") - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("route", "delete", "0.0.0.0", "mask", "128.0.0.0", v.TunGateway) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - c = exec.Command("route", "delete", "128.0.0.0", "mask", "128.0.0.0", v.TunGateway) - c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - gw, err := sysproxy.GetDefaultGateway() - if err != nil { - return err - } - c = exec.Command("route", "delete", v.ServerIP, "mask", "255.255.255.255", gw, "metric", "1") - if out, err := c.CombinedOutput(); err != nil { - return errors.New(string(out) + err.Error()) - } - return nil -}