master
兔子 10 months ago
parent c485d070a3
commit d2feccf3b3

@ -14,6 +14,7 @@ require (
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9
github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/inconshreveable/mousetrap v1.0.1
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/spf13/cobra v1.6.1
)
@ -22,7 +23,6 @@ require (
b612.me/starmap v1.2.3 // indirect
b612.me/starnet v0.1.7 // indirect
b612.me/win32api v0.0.1 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jlaffaye/ftp v0.1.0 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/pkg/sftp v1.13.4 // indirect

@ -11,7 +11,7 @@ import (
var remote, config string
var addr, key, cert, log string
var port int
var enablessl bool
var enablessl, skipsslverify bool
var host string
func init() {
@ -23,6 +23,7 @@ func init() {
Cmd.Flags().StringVarP(&cert, "cert", "c", "", "ssl 证书地址")
Cmd.Flags().StringVarP(&log, "log", "l", "", "log日志地址")
Cmd.Flags().BoolVarP(&enablessl, "enable-ssl", "s", false, "启用ssl")
Cmd.Flags().BoolVarP(&skipsslverify, "skil-ssl-verify", "S", false, "跳过证书验证")
Cmd.Flags().IntVarP(&port, "port", "p", 8080, "监听端口")
}
@ -69,11 +70,12 @@ var Cmd = &cobra.Command{
ReverseURL: map[string]*url.URL{
"/": u,
},
Port: port,
UsingSSL: enablessl,
Key: key,
Cert: cert,
XForwardMode: 1,
Port: port,
UsingSSL: enablessl,
SkipSSLVerify: skipsslverify,
Key: key,
Cert: cert,
XForwardMode: 1,
}
go func() {
sig := make(chan os.Signal)

@ -12,23 +12,24 @@ import (
)
type ReverseConfig struct {
Name string
Addr string
ReverseURL map[string]*url.URL
Port int
UsingSSL bool
Key string
Cert string
Host string
InHeader [][2]string
OutHeader [][2]string
Cookie [][3]string //[3]string should contains path::key::value
ReplaceList [][2]string
ReplaceOnce bool
proxy map[string]*httputil.ReverseProxy
XForwardMode int //0=off 1=useremote 2=add
httpmux http.ServeMux
httpserver http.Server
Name string
Addr string
ReverseURL map[string]*url.URL
Port int
UsingSSL bool
Key string
Cert string
Host string
SkipSSLVerify bool
InHeader [][2]string
OutHeader [][2]string
Cookie [][3]string //[3]string should contains path::key::value
ReplaceList [][2]string
ReplaceOnce bool
proxy map[string]*httputil.ReverseProxy
XForwardMode int //0=off 1=useremote 2=add
httpmux http.ServeMux
httpserver http.Server
basicAuthUser string
basicAuthPwd string

@ -4,9 +4,11 @@ import (
"b612.me/starlog"
"bytes"
"context"
"crypto/tls"
"encoding/base64"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
@ -75,10 +77,61 @@ func (h *ReverseConfig) Close() error {
return h.httpserver.Shutdown(ctx)
}
func (h *ReverseConfig) dialTLS(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(network, addr, time.Second*20)
if err != nil {
return nil, err
}
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
if h.Host != "" {
host = h.Host
}
cfg := &tls.Config{ServerName: host}
tlsConn := tls.Client(conn, cfg)
if err := tlsConn.Handshake(); err != nil {
conn.Close()
return nil, err
}
cs := tlsConn.ConnectionState()
cert := cs.PeerCertificates[0]
// Verify here
if !h.SkipSSLVerify {
err = cert.VerifyHostname(host)
if err != nil {
return nil, err
}
}
return tlsConn, nil
}
func (h *ReverseConfig) init() error {
h.proxy = make(map[string]*httputil.ReverseProxy)
for key, val := range h.ReverseURL {
h.proxy[key] = httputil.NewSingleHostReverseProxy(val)
h.proxy[key] = &httputil.ReverseProxy{
Transport: &http.Transport{DialTLSContext: h.dialTLS},
Director: func(req *http.Request) {
targetQuery := val.RawQuery
req.URL.Scheme = val.Scheme
if h.Host == "" {
req.Host = val.Host
} else {
req.Host = h.Host
}
req.URL.Host = val.Host
req.URL.Path, req.URL.RawPath = joinURLPath(val, req.URL)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
},
}
h.proxy[key].ModifyResponse = h.ModifyResponse()
originalDirector := h.proxy[key].Director
h.proxy[key].Director = func(req *http.Request) {

@ -16,6 +16,7 @@ import (
"b612.me/apps/b612/httpserver"
"b612.me/apps/b612/image"
"b612.me/apps/b612/merge"
"b612.me/apps/b612/net"
"b612.me/apps/b612/search"
"b612.me/apps/b612/split"
"b612.me/apps/b612/tcping"
@ -29,7 +30,7 @@ import (
var cmdRoot = &cobra.Command{
Use: "b612",
Version: "2.0.1",
Version: "2.0.2",
}
func init() {
@ -37,7 +38,7 @@ func init() {
cmdRoot.AddCommand(tcping.Cmd, uac.Cmd, httpserver.Cmd, httpreverse.Cmd,
base64.Cmd, base85.Cmd, base91.Cmd, attach.Cmd, detach.Cmd, df.Cmd, dfinder.Cmd,
ftp.Cmd, generate.Cmd, hash.Cmd, image.Cmd, merge.Cmd, search.Cmd, split.Cmd, vic.Cmd,
calc.Cmd)
calc.Cmd, net.Cmd)
}
func main() {

@ -1 +1,15 @@
package net
import (
"b612.me/apps/b612/netforward"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "net",
Short: "net tools",
}
func init() {
Cmd.AddCommand(netforward.CmdNetforward)
}

@ -1,16 +0,0 @@
package net
import "testing"
func TestForward(t *testing.T) {
var f = NetForward{
LocalAddr: "127.0.0.1",
LocalPort: 22232,
RemoteURI: "127.0.0.1:1127",
EnableTCP: true,
EnableUDP: true,
DialTimeout: 0,
UDPTimeout: 0,
}
f.Run()
}

@ -1,27 +1,27 @@
package net
import (
"b612.me/starlog"
"bytes"
"errors"
"context"
"encoding/hex"
"fmt"
"io"
"net"
"strings"
"sync"
"sync/atomic"
"time"
)
var MSG_CMD_HELLO = []byte{11, 27, 19, 96, 182, 18, 25, 150, 17, 39}
var MSG_NEW_CONN = []byte{0, 0, 0, 0, 255, 255, 255, 255, 11, 27}
var MSG_NEW_CONN_REQ = []byte{0, 0, 0, 0, 255, 255, 255, 255, 19, 96}
var MSG_CLOSE = []byte{255, 255, 0, 0, 255, 0, 0, 255, 255, 27}
var MSG_HEARTBEAT = []byte{6, 66, 66, 6, 6, 66, 6, 66, 11, 27}
// MSG_CMD_HELLO 控制链路主动链接参头 16byte
var MSG_CMD_HELLO, _ = hex.DecodeString("B6121127AF7ECDA1")
var MSG_CMD_HELLO_REPLY, _ = hex.DecodeString("B6121127AF7ECDA2")
type SimpleNatServer struct {
mu sync.RWMutex
// MSG_NEW_CONN_HELLO 交链路主动连接头 16byte
var MSG_NEW_CONN_HELLO, _ = hex.DecodeString("B6121127AF7ECDFF")
type NatServer struct {
sync.RWMutex
cmdTCPConn net.Conn
cmdUDPConn *net.UDPAddr
listenTcp net.Listener
listenUDP *net.UDPConn
Addr string
@ -32,107 +32,58 @@ type SimpleNatServer struct {
DialTimeout int64
UDPTimeout int64
running int32
tcpConnPool chan net.Conn
tcpAlived bool
tcpConnPool chan net.Conn
stopCtx context.Context
stopFn context.CancelFunc
}
func (s *SimpleNatServer) getConnfromTCPPool() (net.Conn, error) {
select {
case conn := <-s.tcpConnPool:
return conn, nil
case <-time.After(time.Second * 10):
return nil, errors.New("no connection got")
func (n *NatServer) Run() error {
if n.running != 0 {
return fmt.Errorf("Server Already Run")
}
n.stopCtx, n.stopFn = context.WithCancel(context.Background())
return nil
}
func (s *SimpleNatServer) tcpCmdConn() net.Conn {
s.mu.RLock()
defer s.mu.RUnlock()
return s.cmdTCPConn
}
func (n *NatServer) cmdTcploop(conn net.Conn) error {
var header = make([]byte, 16)
for {
c, err := conn.Read(header)
if err != nil {
//todo
}
if c != 16 {
func (s *SimpleNatServer) tcpCmdConnAlived() bool {
s.mu.RLock()
defer s.mu.RUnlock()
return s.tcpAlived
}
}
}
func (s *SimpleNatServer) listenTCP() error {
var err error
s.tcpConnPool = make(chan net.Conn, 10)
s.listenTcp, err = net.Listen("tcp", fmt.Sprintf("%s:d", s.Addr, s.Port))
func (n *NatServer) runTcpListen() error {
atomic.AddInt32(&n.running, 1)
defer atomic.AddInt32(&n.running, -1)
listener, err := net.Listen("tcp", n.Addr)
if err != nil {
starlog.Errorln("failed to listen tcp", err)
return err
}
n.listenTcp = listener
for {
conn, err := s.listenTcp.Accept()
conn, err := listener.Accept()
if err != nil {
continue
}
if s.tcpCmdConnAlived() {
go s.tcpClientServe(conn.(*net.TCPConn))
continue
}
go s.waitingForTCPCmd(conn.(*net.TCPConn))
}
return nil
}
func (s *SimpleNatServer) tcpClientServe(conn *net.TCPConn) {
if !s.tcpCmdConnAlived() {
conn.Close()
return
}
if strings.Split(conn.RemoteAddr().String(), ":")[0] == strings.Split(s.tcpCmdConn().RemoteAddr().String(), ":")[0] {
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
cmdBuf := make([]byte, 10)
if _, err := io.ReadFull(conn, cmdBuf); err == nil {
conn.SetReadDeadline(time.Time{})
if bytes.Equal(cmdBuf, MSG_NEW_CONN) {
starlog.Noticef("Nat Server Recv New Client Conn From %v\n", conn.RemoteAddr().String())
s.tcpConnPool <- conn
return
headedr := make([]byte, 16)
conn.SetReadDeadline(time.Now().Add(time.Millisecond * 700))
c, err := conn.Read(headedr)
if err == nil && c == 16 {
if bytes.Equal(headedr, MSG_CMD_HELLO) {
if n.cmdTCPConn != nil {
n.cmdTCPConn.Close()
}
n.cmdTCPConn = conn
conn.Write(MSG_CMD_HELLO_REPLY)
//
}
}
conn.SetReadDeadline(time.Time{})
}
starlog.Noticef("Nat Server Recv New Side Conn From %v\n", conn.RemoteAddr().String())
_, err := s.tcpCmdConn().Write(MSG_NEW_CONN_REQ)
if err != nil {
s.mu.Lock()
s.cmdTCPConn.Close()
s.tcpAlived = false
s.mu.Unlock()
starlog.Errorf("Failed to Write CMD To Client:%v\n", err)
return
}
reverse, err := s.getConnfromTCPPool()
if err != nil {
starlog.Errorf("Nat Server Conn to %v Closed %v\n", conn.RemoteAddr(), err)
conn.Close()
return
}
starlog.Infof("Nat Server Conn %v<==>%v Connected\n", conn.RemoteAddr(), reverse.RemoteAddr())
Copy(reverse, conn)
starlog.Warningf("Nat Server Conn %v<==>%v Closed\n", conn.RemoteAddr(), reverse.RemoteAddr())
}
func (s *SimpleNatServer) waitingForTCPCmd(conn *net.TCPConn) {
conn.SetReadDeadline(time.Now().Add(time.Duration(s.DialTimeout) * time.Second))
cmdBuf := make([]byte, 10)
if _, err := io.ReadFull(conn, cmdBuf); err != nil {
conn.Close()
return
}
if bytes.Equal(cmdBuf, MSG_CMD_HELLO) {
s.mu.Lock()
s.cmdTCPConn = conn
s.tcpAlived = true
conn.SetKeepAlive(true)
conn.SetKeepAlivePeriod(time.Second * 20)
s.mu.Unlock()
io.ReadFull(conn, headedr)
}
}

@ -0,0 +1,67 @@
package netforward
import (
"b612.me/stario"
"b612.me/starlog"
"github.com/spf13/cobra"
"os"
"os/signal"
"strings"
"time"
)
var f = new(NetForward)
var dialTimeout, udpTimeout int64
func init() {
CmdNetforward.Flags().StringVarP(&f.LocalAddr, "local", "l", "0.0.0.0", "bind address")
CmdNetforward.Flags().IntVarP(&f.LocalPort, "port", "p", 11270, "local listen port")
CmdNetforward.Flags().BoolVarP(&f.EnableTCP, "enable-tcp-forward", "t", true, "enable tcp forward mode")
CmdNetforward.Flags().BoolVarP(&f.EnableUDP, "enable-udp-forward", "u", true, "enable udp forward mode")
CmdNetforward.Flags().Int64VarP(&dialTimeout, "dial-timeout", "d", 10000, "dial timeout milliseconds")
CmdNetforward.Flags().Int64VarP(&udpTimeout, "udp-timeout", "D", 60000, "udp connection timeout milliseconds")
}
var CmdNetforward = &cobra.Command{
Use: "forward",
Short: "net forward",
Long: "forward tcp and udp packet",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("please enter a target uri")
os.Exit(1)
}
f.RemoteURI = strings.TrimSpace(args[0])
if dialTimeout == 0 {
dialTimeout = 10000
}
if udpTimeout == 0 {
udpTimeout = 60000
}
f.DialTimeout = time.Duration(dialTimeout) * time.Millisecond
f.UDPTimeout = time.Duration(udpTimeout) * time.Millisecond
if err := f.Run(); err != nil {
starlog.Errorln("run net forward failed:", err)
os.Exit(2)
}
sign := make(chan os.Signal)
signal.Notify(sign, os.Interrupt, os.Kill)
for {
select {
case <-sign:
starlog.Noticeln("Recv Stop Signal From User")
f.stopFn()
case <-stario.WaitUntilFinished(func() error {
for {
if f.Status() == 0 {
return nil
}
time.Sleep(time.Second)
}
}):
starlog.Infoln("Service Stoped")
return
}
}
},
}

@ -1,4 +1,4 @@
package net
package netforward
import (
"b612.me/starlog"
@ -28,35 +28,33 @@ type NetForward struct {
func (n *NetForward) Close() {
n.stopFn()
}
func (n *NetForward) Status() int32 {
return n.running
}
func (n *NetForward) Run() error {
if !atomic.CompareAndSwapInt32(&n.running, 0, 1) {
if n.running > 0 {
starlog.Errorln("already running")
return errors.New("already running")
}
n.stopCtx, n.stopFn = context.WithCancel(context.Background())
if n.DialTimeout == 0 {
n.DialTimeout = time.Second * 10
n.DialTimeout = time.Second * 5
}
var wg sync.WaitGroup
if n.EnableTCP {
wg.Add(1)
go func() {
defer wg.Done()
n.runTCP()
}()
go n.runTCP()
}
if n.EnableUDP {
wg.Add(1)
go func() {
defer wg.Done()
n.runUDP()
}()
go n.runUDP()
}
wg.Wait()
return nil
}
func (n *NetForward) runTCP() error {
atomic.AddInt32(&n.running, 1)
defer atomic.AddInt32(&n.running, -1)
listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", n.LocalAddr, n.LocalPort))
if err != nil {
starlog.Errorln("Listening On Tcp Failed:", err)
@ -68,6 +66,11 @@ func (n *NetForward) runTCP() error {
}()
starlog.Infof("Listening TCP on %v\n", fmt.Sprintf("%s:%d", n.LocalAddr, n.LocalPort))
for {
select {
case <-n.stopCtx.Done():
return nil
default:
}
conn, err := listen.Accept()
if err != nil {
continue
@ -77,13 +80,13 @@ func (n *NetForward) runTCP() error {
go func(conn net.Conn) {
rmt, err := net.DialTimeout("tcp", n.RemoteURI, n.DialTimeout)
if err != nil {
log.Errorf("Dial Remote %s Failed:%v\n", n.RemoteURI, err)
log.Errorf("TCP:Dial Remote %s Failed:%v\n", n.RemoteURI, err)
conn.Close()
return
}
log.Infof("Connect %s <==> %s\n", conn.RemoteAddr().String(), n.RemoteURI)
log.Infof("TCP Connect %s <==> %s\n", conn.RemoteAddr().String(), rmt.RemoteAddr().String())
Copy(rmt, conn)
log.Noticef("Connection Closed %s <==> %s", conn.RemoteAddr().String(), n.RemoteURI)
log.Noticef("TCP Connection Closed %s <==> %s", conn.RemoteAddr().String(), n.RemoteURI)
}(conn)
}
}
@ -124,6 +127,8 @@ func (u UDPConn) Work() {
func (n *NetForward) runUDP() error {
var mu sync.RWMutex
atomic.AddInt32(&n.running, 1)
defer atomic.AddInt32(&n.running, -1)
udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%v", n.LocalAddr, n.LocalPort))
if err != nil {
return err
@ -148,7 +153,7 @@ func (n *NetForward) runUDP() error {
for k, v := range udpMap {
if time.Now().Unix() > int64(n.UDPTimeout.Seconds())+v.lastbeat {
delete(udpMap, k)
starlog.Noticef("Connection Closed %s <==> %s", v.remoteAddr.String(), n.RemoteURI)
starlog.Noticef("UDP Connection Closed %s <==> %s\n", v.remoteAddr.String(), n.RemoteURI)
}
}
mu.Unlock()
@ -157,6 +162,11 @@ func (n *NetForward) runUDP() error {
}()
buf := make([]byte, 8192)
for {
select {
case <-n.stopCtx.Done():
return nil
default:
}
count, rmt, err := listen.ReadFromUDP(buf)
if err != nil || rmt.String() == n.RemoteURI {
continue
@ -169,7 +179,7 @@ func (n *NetForward) runUDP() error {
log.Infof("Accept New UDP Conn from %v\n", rmt.String())
conn, err := net.Dial("udp", n.RemoteURI)
if err != nil {
log.Errorf("Dial Remote %s Failed:%v\n", n.RemoteURI, err)
log.Errorf("UDP:Dial Remote %s Failed:%v\n", n.RemoteURI, err)
mu.Unlock()
return
}
@ -181,7 +191,7 @@ func (n *NetForward) runUDP() error {
}
udpMap[rmt.String()] = addr
go addr.Work()
log.Infof("Connect %s <==> %s\n", rmt.String(), n.RemoteURI)
log.Infof("UDP Connect %s <==> %s\n", rmt.String(), n.RemoteURI)
}
mu.Unlock()
_, err := addr.Write(data)
@ -190,7 +200,7 @@ func (n *NetForward) runUDP() error {
addr.Close()
delete(udpMap, addr.remoteAddr.String())
mu.Unlock()
log.Noticef("Connection Closed %s <==> %s", rmt.String(), n.RemoteURI)
log.Noticef("UDP Connection Closed %s <==> %s\n", rmt.String(), n.RemoteURI)
}
}(buf[0:count], rmt)
}

@ -0,0 +1,33 @@
package netforward
import (
"fmt"
"testing"
"time"
)
func TestForward(t *testing.T) {
var f = NetForward{
LocalAddr: "127.0.0.1",
LocalPort: 22232,
RemoteURI: "192.168.2.1:80",
EnableTCP: true,
EnableUDP: true,
DialTimeout: 6 * time.Second,
UDPTimeout: 7 * time.Second,
}
f.Run()
go func() {
time.Sleep(time.Second * 10)
fmt.Println("closing")
f.Close()
}()
for {
time.Sleep(time.Second * 2)
if f.Status() > 0 {
fmt.Println(f.Status())
continue
}
return
}
}
Loading…
Cancel
Save