Skip to content

Commit

Permalink
$ brook hijackhttps
Browse files Browse the repository at this point in the history
  • Loading branch information
txthinking committed May 20, 2020
1 parent e8f2090 commit af6c2a1
Show file tree
Hide file tree
Showing 13 changed files with 603 additions and 47 deletions.
77 changes: 72 additions & 5 deletions cli/brook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func main() {
},
&cli.StringFlag{
Name: "defaultDNSServer",
Usage: "Default DNS server",
Usage: "DNS server for resolving domains NOT in list",
Value: "8.8.8.8:53",
},
&cli.StringFlag{
Expand Down Expand Up @@ -553,13 +553,11 @@ func main() {
}
s.LetBrookDoAllForMe = c.Bool("letBrookDoAllForMe")
go func() {
fmt.Println("Ctrl-C to quit")
log.Println(s.ListenAndServe())
}()
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
fmt.Println("Quitting...")
return s.Shutdown()
},
},
Expand Down Expand Up @@ -925,7 +923,7 @@ func main() {
&cli.StringFlag{
Name: "socks5",
Aliases: []string{"s"},
Usage: "Socks5 server address",
Usage: "Socks5 server address, like: 127.0.0.1:1080",
},
&cli.StringFlag{
Name: "socks5username",
Expand Down Expand Up @@ -972,6 +970,75 @@ func main() {
return s.ListenAndServe()
},
},
&cli.Command{
Name: "hijackhttps",
Usage: "Hijack domains and assume is TCP/TLS/443. Requesting these domains from anywhere in the system will be hijacked . [src <-> $ brook hijackhttps <-> socks5 server] or [src <-> direct]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "socks5",
Aliases: []string{"s"},
Usage: "Socks5 server address, like: 127.0.0.1:1080",
},
&cli.StringFlag{
Name: "socks5username",
Usage: "Socks5 username, optional",
},
&cli.StringFlag{
Name: "socks5password",
Usage: "Socks5 password, optional",
},
&cli.StringFlag{
Name: "loopbackip",
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",
},
&cli.StringFlag{
Name: "defaultDNSServer",
Usage: "DNS server for resolving domains NOT in list",
Value: "8.8.8.8:53",
},
&cli.StringFlag{
Name: "list",
Usage: "Only domains in list will be hijacked. https://, http:// or local file path",
Value: "https://txthinking.github.io/blackwhite/black.list",
},
&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)",
},
},
Action: func(c *cli.Context) error {
if c.String("socks5") == "" {
cli.ShowCommandHelp(c, "hijackhttps")
return nil
}
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"))
if err != nil {
return err
}
go func() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
s.Shutdown()
}()
return s.ListenAndServe()
},
},
&cli.Command{
Name: "pac",
Usage: "Run as PAC server or save PAC to file",
Expand Down Expand Up @@ -1175,7 +1242,7 @@ func main() {
},
&cli.Command{
Name: "ssclient",
Usage: "Run as shadowsocks client, both TCP and UDP, to start a socks5 proxy or a http proxy, fixed method is aes-256-cfb, [src <-> $ brook ssclient <-> $ brook ssserver <-> dst], [works with $ brook ssserver]",
Usage: "Run as shadowsocks client, both TCP and UDP, to start socks5 or http proxy, method is aes-256-cfb, [src <-> $ brook ssclient <-> $ brook ssserver <-> dst], [works with $ brook ssserver]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "ssserver",
Expand Down
3 changes: 3 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func (x *Client) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Request)
}

if r.Cmd == socks5.CmdConnect {
debug("dial tcp", r.Address())
tmp, err := Dial.Dial("tcp", x.RemoteAddr)
if err != nil {
return ErrorReply(r, c, err)
Expand Down Expand Up @@ -266,6 +267,7 @@ func (x *Client) UDPHandle(s *socks5.Server, addr *net.UDPAddr, d *socks5.Datagr
return send(ue, d.Bytes()[3:])
}

debug("dial udp", d.Address())
c, err := Dial.Dial("udp", x.RemoteAddr)
if err != nil {
v, ok := s.TCPUDPAssociate.Get(addr.String())
Expand Down Expand Up @@ -400,6 +402,7 @@ func (x *Client) HTTPHandle(c *net.TCPConn) error {
return err
}
}
debug("dial http", addr)

if x.HTTPMiddleman != nil {
done, err := x.HTTPMiddleman.Handle(method, addr, b, c)
Expand Down
105 changes: 87 additions & 18 deletions dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package brook

import (
"bytes"
"encoding/binary"
"io"
"io/ioutil"
"log"
Expand Down Expand Up @@ -194,6 +195,81 @@ func (s *DNS) Shutdown() error {

// TCPHandle handles request.
func (s *DNS) TCPHandle(c *net.TCPConn) error {
co := &dns.Conn{Conn: c}
m, err := co.ReadMsg()
if err != nil {
return err
}
has := false
for _, v := range m.Question {
debug("dns query", "udp", v.Qtype, v.Name)
if len(v.Name) > 0 && s.Has(v.Name[0:len(v.Name)-1]) {
has = true
break
}
}
mb, err := m.Pack()
if err != nil {
return err
}
lb := make([]byte, 2)
binary.BigEndian.PutUint16(lb, uint16(len(mb)))
mb = append(lb, mb...)
if has {
debug("in list", "tcp", m.Question[0].Name)
tmp, err := Dial.Dial("tcp", s.ListDNSServer)
if err != nil {
return err
}
rc := tmp.(*net.TCPConn)
defer rc.Close()
if s.TCPTimeout != 0 {
if err := rc.SetKeepAlivePeriod(time.Duration(s.TCPTimeout) * time.Second); err != nil {
return err
}
}
if s.TCPDeadline != 0 {
if err := rc.SetDeadline(time.Now().Add(time.Duration(s.TCPDeadline) * time.Second)); err != nil {
return err
}
}
if _, err := rc.Write(mb); err != nil {
return err
}
go func() {
var bf [1024 * 2]byte
for {
if s.TCPDeadline != 0 {
if err := rc.SetDeadline(time.Now().Add(time.Duration(s.TCPDeadline) * time.Second)); err != nil {
return
}
}
i, err := rc.Read(bf[:])
if err != nil {
return
}
if _, err := c.Write(bf[0:i]); err != nil {
return
}
}
}()
var bf [1024 * 2]byte
for {
if s.TCPDeadline != 0 {
if err := c.SetDeadline(time.Now().Add(time.Duration(s.TCPDeadline) * time.Second)); err != nil {
return nil
}
}
i, err := c.Read(bf[:])
if err != nil {
return nil
}
if _, err := rc.Write(bf[0:i]); err != nil {
return nil
}
}
return nil
}
tmp, err := Dial.Dial("tcp", s.RemoteTCPAddr.String())
if err != nil {
return err
Expand Down Expand Up @@ -231,6 +307,10 @@ func (s *DNS) TCPHandle(c *net.TCPConn) error {
if err != nil {
return err
}
n, _, err = WriteTo(rc, mb, k, n, false)
if err != nil {
return err
}

go func() {
n := make([]byte, 12)
Expand Down Expand Up @@ -286,12 +366,14 @@ func (s *DNS) UDPHandle(addr *net.UDPAddr, b []byte) error {
}
has := false
for _, v := range m.Question {
debug("dns query", "udp", v.Qtype, v.Name)
if len(v.Name) > 0 && s.Has(v.Name[0:len(v.Name)-1]) {
has = true
break
}
}
if has {
debug("in list", "udp", m.Question[0].Name)
conn, err := Dial.Dial("udp", s.ListDNSServer)
if err != nil {
return err
Expand All @@ -305,21 +387,6 @@ func (s *DNS) UDPHandle(addr *net.UDPAddr, b []byte) error {
if err != nil {
return err
}
if m1.MsgHdr.Truncated {
conn, err := Dial.Dial("tcp", s.ListDNSServer)
if err != nil {
return err
}
defer conn.Close()
co := &dns.Conn{Conn: conn}
if err := co.WriteMsg(m); err != nil {
return err
}
m1, err = co.ReadMsg()
if err != nil {
return err
}
}
m1b, err := m1.Pack()
if err != nil {
return err
Expand Down Expand Up @@ -435,9 +502,11 @@ func readList(url string) ([]string, error) {
return nil, err
}
}
data, err = ioutil.ReadFile(url)
if err != nil {
return nil, err
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
data, err = ioutil.ReadFile(url)
if err != nil {
return nil, err
}
}
data = bytes.TrimSpace(data)
data = bytes.Replace(data, []byte{0x20}, []byte{}, -1)
Expand Down
Loading

0 comments on commit af6c2a1

Please sign in to comment.