Skip to content

Commit

Permalink
fixed txthinking#7
Browse files Browse the repository at this point in the history
  • Loading branch information
txthinking committed Mar 30, 2017
1 parent 59c10da commit 103ddaa
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 2 deletions.
139 changes: 138 additions & 1 deletion bkclient.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package brook

import (
"bytes"
"crypto/aes"
"crypto/rand"
"errors"
"io"
"log"
"net"
Expand Down Expand Up @@ -72,6 +74,32 @@ func (c *BKClient) ListenAndServe() error {
}
}

// ListenAndServeHTTP will let client start a http(s) proxy to listen and serve
func (c *BKClient) ListenAndServeHTTP() error {
ta, err := net.ResolveTCPAddr("tcp", c.Address)
if err != nil {
return err
}
l, err := net.ListenTCP("tcp", ta)
if err != nil {
return err
}
defer l.Close()
c.Listen = l

for {
conn, err := l.AcceptTCP()
if err != nil {
return err
}
go func(conn *net.TCPConn) {
if err := c.handleHTTP(conn); err != nil {
log.Println(err)
}
}(conn)
}
}

// Shutdown used to stop the client
func (c *BKClient) Shutdown() error {
if c.Listen == nil {
Expand Down Expand Up @@ -162,7 +190,19 @@ func (c *BKClient) handle(conn *net.TCPConn) error {
}
return err
}
a, addr, port := socks5.ParseAddress(crc.LocalAddr())
a, addr, port, err := socks5.ParseAddress(crc.LocalAddr().String())
if err != nil {
var p *socks5.Reply
if request.Atyp == socks5.ATYPIPv4 || request.Atyp == socks5.ATYPDomain {
p = socks5.NewReply(socks5.RepConnectionRefused, socks5.ATYPIPv4, []byte{0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00})
} else {
p = socks5.NewReply(socks5.RepConnectionRefused, socks5.ATYPIPv6, []byte(net.IPv6zero), []byte{0x00, 0x00})
}
if err := p.WriteTo(conn); err != nil {
return err
}
return err
}
if err := socks5.NewReply(socks5.RepSuccess, a, addr, port).WriteTo(conn); err != nil {
return err
}
Expand All @@ -173,6 +213,103 @@ func (c *BKClient) handle(conn *net.TCPConn) error {
return nil
}

func (c *BKClient) handleHTTP(conn *net.TCPConn) error {
defer conn.Close()
if c.Timeout != 0 {
if err := conn.SetKeepAlivePeriod(time.Duration(c.Timeout) * time.Second); err != nil {
return err
}
}
if c.Deadline != 0 {
if err := conn.SetDeadline(time.Now().Add(time.Duration(c.Deadline) * time.Second)); err != nil {
return err
}
}

b := make([]byte, 0, 1024)
for {
var b1 [50]byte
n, err := conn.Read(b1[:])
if err != nil {
return err
}
b = append(b, b1[:n]...)
if bytes.Contains(b, []byte{0x0d, 0x0a, 0x0d, 0x0a}) {
break
}
}
bb := bytes.SplitN(b, []byte(" "), 3)
if len(bb) != 3 {
return errors.New("Invalid Request")
}
method, aoru := string(bb[0]), string(bb[1])
var addr string
if method == "CONNECT" {
addr = aoru
} else {
var err error
addr, err = GetAddressFromURL(aoru)
if err != nil {
return err
}
}
a, h, p, err := socks5.ParseAddress(addr)
if err != nil {
return err
}
rawaddr := make([]byte, 0)
rawaddr = append(rawaddr, a)
rawaddr = append(rawaddr, h...)
rawaddr = append(rawaddr, p...)

rc, err := c.Dial.Dial("tcp", c.Server)
if err != nil {
return err
}
defer rc.Close()
if c.Timeout != 0 {
if rtc, ok := rc.(*net.TCPConn); ok {
if err := rtc.SetKeepAlivePeriod(time.Duration(c.Timeout) * time.Second); err != nil {
return err
}
}
}
if c.Deadline != 0 {
if err := rc.SetDeadline(time.Now().Add(time.Duration(c.Deadline) * time.Second)); err != nil {
return err
}
}
if c.Music != nil {
if _, err := rc.Write(c.Music.GetSong()); err != nil {
return err
}
}
crc, err := c.wrapCipherConn(rc)
if err != nil {
return err
}
if _, err := crc.Write(rawaddr); err != nil {
return err
}
if method == "CONNECT" {
_, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
if err != nil {
return err
}
}
if method != "CONNECT" {
if _, err := crc.Write(b); err != nil {
return err
}
}

go func() {
_, _ = io.Copy(conn, crc)
}()
_, _ = io.Copy(crc, conn)
return nil
}

func (c *BKClient) wrapCipherConn(conn net.Conn) (*CipherConn, error) {
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
Expand Down
7 changes: 7 additions & 0 deletions cli/brook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ func main() {
Name: "listen, l",
Usage: "Client listen address: like: 127.0.0.1:1080",
},
cli.BoolFlag{
Name: "http",
Usage: "If true, client start a http(s) proxy. default socks5",
},
cli.StringFlag{
Name: "server, s",
Usage: "Server address, like: 1.2.3.4:1080",
Expand Down Expand Up @@ -161,6 +165,9 @@ func main() {
if debug {
enableDebug()
}
if c.Bool("http") {
return brook.RunBKHTTPClient(c.String("listen"), c.String("server"), c.String("password"), c.Int("timeout"), c.Int("deadline"), c.String("music"))
}
return brook.RunBKClient(c.String("listen"), c.String("server"), c.String("password"), c.Int("timeout"), c.Int("deadline"), c.String("music"))
},
},
Expand Down
9 changes: 9 additions & 0 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ func RunBKClient(address, server, password string, timeout, deadline int, m stri
return c.ListenAndServe()
}

// RunBKClient used to make a new BKClient and start a http proxy to listen
func RunBKHTTPClient(address, server, password string, timeout, deadline int, m string) error {
c, err := NewBKClient(address, server, password, timeout, deadline, m, nil)
if err != nil {
return err
}
return c.ListenAndServeHTTP()
}

// RunS5Server used to make a new S5Server and start to listen
func RunS5Server(address, password string, timeout, deadline int) error {
s := NewS5Server(address, password, timeout, deadline)
Expand Down
14 changes: 13 additions & 1 deletion ssclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,19 @@ func (c *SSClient) handle(conn *net.TCPConn) error {
}
return err
}
a, addr, port := socks5.ParseAddress(rc.LocalAddr())
a, addr, port, err := socks5.ParseAddress(rc.LocalAddr().String())
if err != nil {
var p *socks5.Reply
if request.Atyp == socks5.ATYPIPv4 || request.Atyp == socks5.ATYPDomain {
p = socks5.NewReply(socks5.RepConnectionRefused, socks5.ATYPIPv4, []byte{0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00})
} else {
p = socks5.NewReply(socks5.RepConnectionRefused, socks5.ATYPIPv6, []byte(net.IPv6zero), []byte{0x00, 0x00})
}
if err := p.WriteTo(conn); err != nil {
return err
}
return err
}
if err := socks5.NewReply(socks5.RepSuccess, a, addr, port).WriteTo(conn); err != nil {
return err
}
Expand Down
23 changes: 23 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package brook

import (
"net"
"net/url"
"regexp"
)

func GetAddressFromURL(s string) (string, error) {
u, err := url.Parse(s)
if err != nil {
return "", err
}
if HasPort(u.Host) {
return u.Host, nil
}
return net.JoinHostPort(u.Host, "80"), nil
}

func HasPort(host string) bool {
r := regexp.MustCompile(`.+:\d+$`)
return r.MatchString(host)
}

0 comments on commit 103ddaa

Please sign in to comment.