Skip to content

Commit

Permalink
Support configuration proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
wzshiming committed Jan 10, 2021
1 parent 95d0bcf commit a5e0c13
Show file tree
Hide file tree
Showing 7 changed files with 425 additions and 83 deletions.
200 changes: 135 additions & 65 deletions bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
"os"
"strconv"
"strings"
"sync"

"github.com/wzshiming/anyproxy"
"github.com/wzshiming/bridge"
"github.com/wzshiming/bridge/chain"
"github.com/wzshiming/bridge/internal/anyproxy"
"github.com/wzshiming/bridge/internal/common"
"github.com/wzshiming/bridge/internal/dump"
"github.com/wzshiming/bridge/internal/log"
Expand All @@ -28,9 +29,9 @@ func Bridge(ctx context.Context, listens, dials []string, d bool) error {
dialer bridge.Dialer = local.LOCAL
listenConfig bridge.ListenConfig = local.LOCAL
)

dial := dials[0]
dials = dials[1:]

if len(dials) != 0 {
b, err := chain.Default.BridgeChain(local.LOCAL, dials...)
if err != nil {
Expand All @@ -39,6 +40,7 @@ func Bridge(ctx context.Context, listens, dials []string, d bool) error {
dialer = b
}

// No listener is set, use stdio.
if len(listens) == 0 {
var raw io.ReadWriteCloser = struct {
io.ReadCloser
Expand All @@ -52,76 +54,140 @@ func Bridge(ctx context.Context, listens, dials []string, d bool) error {
raw = dump.NewDumpReadWriteCloser(raw, true, "STDIO", dial)
}
return step(ctx, dialer, raw, dial)
} else {
network, listen, ok := scheme.SplitSchemeAddr(listens[0])
if !ok {
return fmt.Errorf("unsupported protocol format %q", listens[0])
}
listens = listens[1:]
}

if len(listens) != 0 {
d, err := chain.Default.BridgeChain(local.LOCAL, listens...)
if err != nil {
return err
}
l, ok := d.(bridge.ListenConfig)
if !ok || l == nil {
return errors.New("the last proxy could not listen")
}
listenConfig = l
listen := listens[0]
listens = listens[1:]

if len(listens) != 0 {
d, err := chain.Default.BridgeChain(local.LOCAL, listens...)
if err != nil {
return err
}
l, ok := d.(bridge.ListenConfig)
if !ok || l == nil {
return errors.New("the last proxy could not listen")
}
listenConfig = l
}

if dial != "-" {
return bridgeTCP(ctx, listenConfig, dialer, listen, dial, d)
} else {
return bridgeProxy(ctx, listenConfig, dialer, listen, d)
}
}

func bridgeTCP(ctx context.Context, listenConfig bridge.ListenConfig, dialer bridge.Dialer, listen string, dial string, d bool) error {
listens := strings.Split(listen, ",")
listeners := []net.Listener{}
for _, l := range listens {
network, listen, ok := scheme.SplitSchemeAddr(l)
if !ok {
return fmt.Errorf("unsupported protocol format %q", l)
}
listener, err := listenConfig.Listen(ctx, network, listen)
if err != nil {
return err
}
if ctx != context.Background() {
go func() {
<-ctx.Done()
listeners = append(listeners, listener)
}
if ctx != context.Background() {
go func() {
<-ctx.Done()
for _, listener := range listeners {
listener.Close()
}()
}
}
}()
}

if dial == "-" {
if d {
for {
raw, err := listener.Accept()
if err != nil {
return ignoreClosedErr(err)
wg := sync.WaitGroup{}
wg.Add(len(listeners))
for _, listener := range listeners {
go func(listener net.Listener) {
defer wg.Done()
for {

raw, err := listener.Accept()
if err != nil {
if ignoreClosedErr(err) != nil {
log.Println(err)
}
from := raw.RemoteAddr().String()
svc := anyproxy.NewAnyProxy(ctx, bridge.DialFunc(func(ctx context.Context, network, address string) (c net.Conn, err error) {
c, err = dialer.DialContext(ctx, network, address)
if err != nil {
return nil, err
}
return dump.NewDumpConn(c, false, from, address), nil
}), log.Std, pool.Bytes)
go svc.ServeConn(raw)
return
}
} else {
svc := anyproxy.NewAnyProxy(ctx, dialer, log.Std, pool.Bytes)
for {
raw, err := listener.Accept()
if err != nil {
return ignoreClosedErr(err)
}
go svc.ServeConn(raw)
if d {
raw = dump.NewDumpConn(raw, true, raw.RemoteAddr().String(), dial)
}
go stepIgnoreErr(ctx, dialer, raw, dial)
}
} else {
}(listener)
}
wg.Wait()
return nil
}

func bridgeProxy(ctx context.Context, listenConfig bridge.ListenConfig, dialer bridge.Dialer, listen string, d bool) error {
listens := strings.Split(listen, ",")
svc, err := anyproxy.NewAnyProxy(ctx, listens, dialer)
if err != nil {
return err
}
hosts := svc.Hosts()
listeners := []net.Listener{}
for _, listen := range hosts {
listener, err := listenConfig.Listen(ctx, "tcp", listen)
if err != nil {
return err
}
listeners = append(listeners, listener)
}
if ctx != context.Background() {
go func() {
<-ctx.Done()
for _, listener := range listeners {
listener.Close()
}
}()
}

wg := sync.WaitGroup{}
wg.Add(len(listeners))
for i, listener := range listeners {
go func(host string, listener net.Listener) {
defer wg.Done()
h := svc.Match(host)
for {
raw, err := listener.Accept()
if err != nil {
return ignoreClosedErr(err)
if ignoreClosedErr(err) != nil {
log.Println(err)
}
return
}
h := h
if d {
raw = dump.NewDumpConn(raw, true, raw.RemoteAddr().String(), dial)
// In dubug mode, need to know the address of the client.
// Because it is debug, performance is not considered here.
dial := bridge.DialFunc(func(ctx context.Context, network, address string) (c net.Conn, err error) {
c, err = dialer.DialContext(ctx, network, address)
if err != nil {
return nil, err
}
return dump.NewDumpConn(c, false, raw.RemoteAddr().String(), address), nil
})
svc, err := anyproxy.NewAnyProxy(ctx, listens, dial)
if err != nil {
log.Println(err)
return
}
h = svc.Match(host)
}
go stepIgnoreErr(ctx, dialer, raw, dial)
go h.ServeConn(raw)
}
}
}(hosts[i], listener)
}
wg.Wait()
return nil
}

func ignoreClosedErr(err error) error {
Expand Down Expand Up @@ -167,23 +233,27 @@ func ShowChain(dials, listens []string) string {
return fmt.Sprintln("DIAL", strings.Join(dials, " <- "), "<- LOCAL <-", strings.Join(listens, " <- "), "LISTEN")
}

func removeUserInfo(s []string) []string {
s = stringsClone(s)
for i := 0; i != len(s); i++ {
sch, addr, ok := scheme.SplitSchemeAddr(s[i])
if !ok {
continue
}
p, ok := scheme.JoinSchemeAddr(sch, addr)
if !ok {
continue
func removeUserInfo(addresses []string) []string {
addresses = stringsClone(addresses)
for i := 0; i != len(addresses); i++ {
address := strings.Split(addresses[i], ",")
for j := 0; j != len(address); j++ {
sch, addr, ok := scheme.SplitSchemeAddr(address[j])
if !ok {
continue
}
p, ok := scheme.JoinSchemeAddr(sch, addr)
if !ok {
continue
}
address[j] = p
}
s[i] = p
addresses[i] = strings.Join(address, ",")
}
for i := 0; i != len(s); i++ {
s[i] = strconv.Quote(s[i])
for i := 0; i != len(addresses); i++ {
addresses[i] = strconv.Quote(addresses[i])
}
return s
return addresses
}

func stringsClone(s []string) []string {
Expand Down
13 changes: 13 additions & 0 deletions cmd/bridge/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"context"
"fmt"
"os"
"strings"
"syscall"

flag "github.com/spf13/pflag"
"github.com/wzshiming/bridge/bridge"
_ "github.com/wzshiming/bridge/command"
_ "github.com/wzshiming/bridge/connect"
"github.com/wzshiming/bridge/internal/log"
"github.com/wzshiming/bridge/internal/scheme"
_ "github.com/wzshiming/bridge/netcat"
_ "github.com/wzshiming/bridge/shadowsocks"
_ "github.com/wzshiming/bridge/smux"
Expand Down Expand Up @@ -57,6 +59,17 @@ func init() {
}

func main() {
if len(dials) > 0 && len(listens) > 0 && dials[0] == "-" {
proxies := strings.Split(listens[0], ",")
if len(proxies) == 1 {
network, address, _ := scheme.SplitSchemeAddr(proxies[0])
if network == "tcp" {
proxies = []string{"http://" + address, "socks5://" + address, "socks4://" + address}
}
}
listens[0] = strings.Join(proxies, ",")
}

log.Println(bridge.ShowChain(dials, listens))
err := bridge.Bridge(ctx, listens, dials, dump)
if err != nil {
Expand Down
11 changes: 5 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ go 1.15

require (
github.com/spf13/pflag v1.0.5
github.com/wzshiming/anyproxy v0.2.1
github.com/wzshiming/cmux v0.1.0
github.com/wzshiming/cmux v0.1.1
github.com/wzshiming/commandproxy v0.2.0
github.com/wzshiming/httpproxy v0.3.2
github.com/wzshiming/httpproxy v0.3.4
github.com/wzshiming/notify v0.0.5
github.com/wzshiming/shadowsocks v0.1.0
github.com/wzshiming/socks4 v0.2.2
github.com/wzshiming/socks5 v0.2.2
github.com/wzshiming/shadowsocks v0.1.1
github.com/wzshiming/socks4 v0.2.3
github.com/wzshiming/socks5 v0.2.3
github.com/xtaci/smux v1.5.15
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
Expand Down
22 changes: 10 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,22 @@ github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmH
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/wzshiming/anyproxy v0.2.1 h1:ow9cdAd3SrAwDjSBiC0EORBn0VPjYZ2R/kS3/cj7xMg=
github.com/wzshiming/anyproxy v0.2.1/go.mod h1:q+FjIanpYG1hhHT9dqIzwcdIo3Y5m4x9zKh/gOzGfm8=
github.com/wzshiming/cmux v0.1.0 h1:MOsZjdVkcuptYBysE85x2ng/ajVSwwUfRLG6GL2IBNg=
github.com/wzshiming/cmux v0.1.0/go.mod h1:B5bzinbIDlFcjtWhdEiEdMWMp41bbd2a7/ghkMuKTUI=
github.com/wzshiming/cmux v0.1.1 h1:njiTsaiG2Fz1B3n9mpLxCS9vGI4EQWSAlpBO71aRHYU=
github.com/wzshiming/cmux v0.1.1/go.mod h1:B5bzinbIDlFcjtWhdEiEdMWMp41bbd2a7/ghkMuKTUI=
github.com/wzshiming/commandproxy v0.2.0 h1:uPVhgIj2YSncRUo6g9smGR6OMzsIg7lwklcMHPPmEeM=
github.com/wzshiming/commandproxy v0.2.0/go.mod h1:wS6+aJ9KMHciqYX3xmDO0W+QVY0zvngeBvmoIFMfq8A=
github.com/wzshiming/crun v0.3.3 h1:Vy3kp+KKfNnkxM+thmiv6HkSsviupMZEI31HtoVZpeY=
github.com/wzshiming/crun v0.3.3/go.mod h1:iYiD/hU/91oBohiLF/F5nGoLlDsHCnp1FCh8WozXayk=
github.com/wzshiming/httpproxy v0.3.2 h1:FuJE8DIQw6UfAf7NAyiZvQJcY1VCD0L0Q1P0f57ageo=
github.com/wzshiming/httpproxy v0.3.2/go.mod h1:3klJUWMVtAFnHcLB1dTyijHLeAVcoSxbvLC7AQH5v4k=
github.com/wzshiming/httpproxy v0.3.4 h1:HpDmF0jQv83zMtMSJgd2CA41OlX98yNMJDnHnZPOXKY=
github.com/wzshiming/httpproxy v0.3.4/go.mod h1:drZR+iQLfYsQi7/nETLjyB9Z0f5KDXQo2PEkJBbg3xQ=
github.com/wzshiming/notify v0.0.5 h1:c/S99kE2S1jNt74hg5bpmM0DFATEHNg5NDgl8sYKAfo=
github.com/wzshiming/notify v0.0.5/go.mod h1:SFhsQKZJznzsDcj/Qfo9A65k5IRcpUrpgbLRzZEa/DI=
github.com/wzshiming/shadowsocks v0.1.0 h1:/p5AiSb3+aEegTkUw4Z6VHUWdaluDjpU1wlHDPlWINM=
github.com/wzshiming/shadowsocks v0.1.0/go.mod h1:56WQwfUpgC/HMhZFNOVTBCP9nbMvL5rAepKRIkSKPsg=
github.com/wzshiming/socks4 v0.2.2 h1:CEzJyGhvDAMpllnRDCrUvgviN0CPBIE3++YgVf/wdqQ=
github.com/wzshiming/socks4 v0.2.2/go.mod h1:YEPfhjf/4JezwdTmgXZU+UX+A2KvD05quzhsUBVMNA0=
github.com/wzshiming/socks5 v0.2.2 h1:lD9SuwAO3ZuBuM8WHVAB5XSmiRl3c60nz4gcIAe0N8Q=
github.com/wzshiming/socks5 v0.2.2/go.mod h1:BvCAqlzocQN5xwLjBZDBbvWlrx8sCYSSbHEOf2wZgT0=
github.com/wzshiming/shadowsocks v0.1.1 h1:G1MFEDkLUg4FThTedfWIEX6Le4fFS3ZTN61m3q3szU0=
github.com/wzshiming/shadowsocks v0.1.1/go.mod h1:56WQwfUpgC/HMhZFNOVTBCP9nbMvL5rAepKRIkSKPsg=
github.com/wzshiming/socks4 v0.2.3 h1:H22IqBxSlWkXC6pZIN9y3ftqhc99TObRSjZQHKdtHqc=
github.com/wzshiming/socks4 v0.2.3/go.mod h1:YEPfhjf/4JezwdTmgXZU+UX+A2KvD05quzhsUBVMNA0=
github.com/wzshiming/socks5 v0.2.3 h1:5fj2WKTwe8OmsfC1qjhkEueQUGirQGxk5MSEGt61PYc=
github.com/wzshiming/socks5 v0.2.3/go.mod h1:BvCAqlzocQN5xwLjBZDBbvWlrx8sCYSSbHEOf2wZgT0=
github.com/wzshiming/trie v0.0.1 h1:6xnhRyO5tZWR6aKjEpFfm8KSNNHYsNbpKrY1+NdyHME=
github.com/wzshiming/trie v0.0.1/go.mod h1:Z20IrQFTHnjWz//dssIoiEPWInBZFyuFlPOFPxV0Rec=
github.com/xtaci/smux v1.5.15 h1:6hMiXswcleXj5oNfcJc+DXS8Vj36XX2LaX98udog6Kc=
Expand Down
Loading

0 comments on commit a5e0c13

Please sign in to comment.