Skip to content

Commit

Permalink
add tcp only middleman
Browse files Browse the repository at this point in the history
  • Loading branch information
txthinking committed Mar 2, 2019
1 parent ca703da commit 0d690a5
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 5 deletions.
5 changes: 1 addition & 4 deletions plugin/middleman/blackwhite/blackwhite.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,7 @@ func (b *BlackWhite) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Reque
}
return true, nil
}
if r.Cmd == socks5.CmdUDP {
return false, nil
}
return false, socks5.ErrUnsupportCmd
return false, nil
}

// UDPHandle handles udp packet.
Expand Down
124 changes: 124 additions & 0 deletions plugin/middleman/tcponly/tcponly.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (c) 2016-present Cloud <cloud@txthinking.com>
//
// 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 <https://www.gnu.org/licenses/>.

package tcponly

import (
"net"
"time"

"github.com/txthinking/socks5"
"github.com/txthinking/x"
)

var Dial x.Dialer = x.DefaultDial

// TCPOnly is a middleman.
type TCPOnly struct {
Timeout int
Deadline int
Socks5Handle socks5.Handler
}

// NewTCPOnly returns a TCPOnly.
func NewTCPOnly(timeout, deadline int) *TCPOnly {
return &TCPOnly{
Timeout: timeout,
Deadline: deadline,
Socks5Handle: &socks5.DefaultHandle{},
}
}

// TCPHandle handles tcp request.
func (t *TCPOnly) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Request) (bool, error) {
if r.Cmd == socks5.CmdUDP {
if err := t.Socks5Handle.TCPHandle(s, c, r); err != nil {
return true, err
}
return true, nil
}
return false, nil
}

// UDPHandle handles udp packet.
func (t *TCPOnly) UDPHandle(s *socks5.Server, ca *net.UDPAddr, d *socks5.Datagram) (bool, error) {
if err := t.Socks5Handle.UDPHandle(s, ca, d); err != nil {
return true, err
}
return true, nil
}

// Handle handles http proxy request, if the domain is in the white list.
func (t *TCPOnly) Handle(method, addr string, request []byte, conn *net.TCPConn) (handled bool, err error) {
tmp, err := Dial.Dial("tcp", addr)
if err != nil {
return true, err
}
rc := tmp.(*net.TCPConn)
defer rc.Close()
if t.Timeout != 0 {
if err := rc.SetKeepAlivePeriod(time.Duration(t.Timeout) * time.Second); err != nil {
return true, err
}
}
if t.Deadline != 0 {
if err := rc.SetDeadline(time.Now().Add(time.Duration(t.Deadline) * time.Second)); err != nil {
return true, err
}
}
if method == "CONNECT" {
_, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
if err != nil {
return true, err
}
}
if method != "CONNECT" {
if _, err := rc.Write(request); err != nil {
return true, err
}
}
go func() {
var bf [1024 * 2]byte
for {
if t.Deadline != 0 {
if err := conn.SetDeadline(time.Now().Add(time.Duration(t.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 t.Deadline != 0 {
if err := rc.SetDeadline(time.Now().Add(time.Duration(t.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
}
2 changes: 1 addition & 1 deletion vpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func NewVPN(addr, server, password string, tcpTimeout, tcpDeadline, udpDeadline,
if err != nil {
return nil, err
}
t := gotun2socks.New(f, addr, []string{"8.8.8.8"}, true, true)
t := gotun2socks.New(f, addr, []string{"8.8.8.8"}, false, true)
return &VPN{
Client: c,
Tunnel: tl,
Expand Down

0 comments on commit 0d690a5

Please sign in to comment.