feature: use tproxy and multi forward(alpha)

This commit is contained in:
ICKelin
2021-05-13 21:33:20 +08:00
parent c375a4a807
commit eff3b509db
25 changed files with 128 additions and 303 deletions

View File

@@ -15,3 +15,6 @@
2018.08.30
Refactor code.
2021.05.13
use tproxy for traffic redirect, support multi forwards eg: CN, US

View File

@@ -1,18 +0,0 @@
name="us-node-1-1"
istap=false
[server]
listen=":9623"
auth_key="gtun-cs-token"
nameservers=["8.8.8.8", "8.8.4.4"]
#route_url="http://www.ipdeny.com/ipblocks/data/countries/us.zone"
[dhcp]
cidr="100.64.240.1/24"
gateway="100.64.240.1"
nameserver="8.8.8.8"
[log]
level="debug"
path="log.log"
days=3

View File

@@ -0,0 +1,8 @@
server:
listen: ":9098"
authKey: "rewrite with your auth key"
log:
days: 5
level: "info"
path: "gtund.log"

View File

@@ -1,2 +1,2 @@
#!/usr/bin/env bash
/gtund -c /gtund.conf
/gtund -c /gtund.yaml

8
NEWS
View File

@@ -1,8 +0,0 @@
- Plugins System
Writting plugin extention such as dns plugin
- app
To controller ip, domain and reverse configuration
- TUN/TAP device DNAT to local port
Userland Conntrack Flow

View File

@@ -1,32 +1,14 @@
[![Build Status](https://travis-ci.org/ICKelin/gtun.svg?branch=master)](https://travis-ci.org/ICKelin/gtun)
### gtun
Gtun is a game or ip accelator written in golang. Currently only support mac os and linux.
### Build
```
./makefile.sh
```
More information, reference.travils.yml
### example
- ip accelator
![ip accelator](./ip_accelator.jpg)
- tunnel
![tunnel](./tunnel.jpg)
### thanks
[songgao/water](https://github.com/songgao/water)
### more
[tun/tap vpn](https://github.com/ICKelin/article/issues/9)
any [issues](https://github.com/ICKelin/gtun/issues/new) are welcome
## gtun
<a href="">
<img src="https://img.shields.io/badge/-Go-000?&logo=go">
</a>
<a href="https://goreportcard.com/report/github.com/ICKelin/gtun" rel="nofollow">
<img src="https://goreportcard.com/badge/github.com/ICKelin/gtun" alt="go report">
</a>
<a href="https://travis-ci.org/ICKelin/gtun" rel="nofollow">
<img src="https://travis-ci.org/ICKelin/gtun.svg?branch=master" alt="Build Status">
</a>
<a href="https://github.com/ICKelin/gtun/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
</a>

View File

@@ -1,8 +0,0 @@
[client]
server = "192.168.31.65:9399"
auth="gtun-cs-token"
[log]
level="debug"
path="log.log"
days=3

View File

@@ -1,10 +0,0 @@
{
"name":"US",
"god_config":{
"god_hb_interval": 3,
"god_conn_timeout":10,
"god_addr": "127.0.0.1:9623",
"must": false,
"token": "gtun-sg-token"
}
}

View File

@@ -1,16 +0,0 @@
name="us-node-1-1"
[server]
listen=":9623"
auth_key="gtun-cs-token"
nameservers=["8.8.8.8", "8.8.4.4"]
[dhcp]
cidr="100.64.240.1/24"
gateway="100.64.240.1"
nameserver="8.8.8.8"
[log]
level="debug"
path="log.log"
days=3

View File

@@ -1,96 +0,0 @@
package common
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"net"
"time"
)
const (
MAX_PAYLOAD = 1<<16 - 1
)
const (
CODE_SUCCESS = 10000
CODE_REGISTER_FAIL = 10001
CODE_FAIL = 99999
)
var version = "1.1.0"
func Version() string {
return version
}
type ResponseBody struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
func Response(data interface{}, err error) []byte {
g2s := &ResponseBody{}
if err != nil {
g2s.Code = CODE_FAIL
g2s.Message = err.Error()
g2s.Data = data
} else {
g2s.Code = CODE_SUCCESS
g2s.Message = "success"
g2s.Data = data
}
bytes, _ := json.Marshal(g2s)
return bytes
}
func Encode(cmd byte, payload []byte) ([]byte, error) {
buff := make([]byte, 0)
if len(payload) > MAX_PAYLOAD {
return nil, fmt.Errorf("too big payload")
}
plen := make([]byte, 2)
binary.BigEndian.PutUint16(plen, uint16(len(payload))+1)
buff = append(buff, plen...)
buff = append(buff, cmd)
buff = append(buff, payload...)
return buff, nil
}
func Decode(conn net.Conn) (byte, []byte, error) {
plen := make([]byte, 2)
conn.SetReadDeadline(time.Now().Add(time.Second * 10))
_, err := io.ReadFull(conn, plen)
conn.SetReadDeadline(time.Time{})
if err != nil {
return 0, nil, err
}
payloadlength := binary.BigEndian.Uint16(plen)
if payloadlength > 65535 {
return 0, nil, fmt.Errorf("too big ippkt size %d", payloadlength)
}
resp := make([]byte, payloadlength)
nr, err := io.ReadFull(conn, resp)
if err != nil {
return 0, nil, err
}
if nr < 1 {
return 0, nil, fmt.Errorf("invalid pkt")
}
if nr != int(payloadlength) {
return resp[0], resp[1:nr], fmt.Errorf("invalid payloadlength %d %d", nr, int(payloadlength))
}
return resp[0], resp[1:nr], nil
}

View File

@@ -1,40 +0,0 @@
package common
// S => gtund(gtun server)
// C => gtun(gtun client)
const (
C2C_DATA = byte(0x00)
C2S_DATA = byte(0x01)
S2C_DATA = byte(0x02)
C2S_HEARTBEAT = byte(0x03)
S2C_HEARTBEAT = byte(0x04)
C2S_AUTHORIZE = byte(0x05)
S2C_AUTHORIZE = byte(0x06)
)
var os = map[string]int{
"linux": 1,
"darwin": 2,
"windows": 3,
}
func OSID(goos string) int {
return os[goos]
}
type C2SAuthorize struct {
Version string `json:"version"`
OS int `json:"os"`
Key string `json:"key"`
}
type S2CAuthorize struct {
Status string `json:"status"`
AccessIP string `json:"access_ip"`
Nameservers []string `json:"nameservers"`
Gateway string `json:"gateway"`
RouteScriptUrl string `json:"route_script_url"`
}

View File

@@ -1,9 +0,0 @@
[client]
server = "192.168.1.2:9091"
auth="gtun-cs-token"
[registry]
addr="http://127.0.0.1:9093"
token="gtun-cr-token"
must=false

20
etc/gtun.yaml Normal file
View File

@@ -0,0 +1,20 @@
forwards:
US:
server: "127.0.0.1:9098"
authKey: "rewrite with your auth key"
tcp:
listenAddr: ":8098"
udp:
listenAddr: ":8098"
CN:
server: "127.0.0.1:9097"
authKey: "rewrite with your auth key"
tcp:
listenAddr: ":8097"
udp:
listenAddr: ":8097"
logs:
days: 5
level: "info"
path: "gtund.log"

8
etc/gtund.yaml Normal file
View File

@@ -0,0 +1,8 @@
server:
listen: ":9098"
authKey: "rewrite with your auth key"
log:
days: 5
level: "info"
path: "gtund.log"

1
go.mod
View File

@@ -24,4 +24,5 @@ require (
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 // indirect
github.com/xtaci/smux v2.0.1+incompatible
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
gopkg.in/yaml.v2 v2.3.0
)

1
go.sum
View File

@@ -318,6 +318,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -8,11 +8,10 @@ import (
"github.com/hashicorp/yamux"
)
var defaultRegion = "US"
type ClientConfig struct {
ServerAddr string `toml:"server"`
AuthKey string `toml:"auth"`
Region string
ServerAddr string
AuthKey string
}
type Client struct {
@@ -31,7 +30,7 @@ func (client *Client) Run() {
for {
conn, err := net.DialTimeout("tcp", client.cfg.ServerAddr, time.Second*10)
if err != nil {
logs.Error("connect to server fail: %v", err)
logs.Error("connect to %s fail: %v", client.cfg.ServerAddr, err)
time.Sleep(time.Second * 3)
continue
}
@@ -43,14 +42,14 @@ func (client *Client) Run() {
continue
}
sess := newSession(mux, defaultRegion)
client.sessionMgr.AddSession(defaultRegion, sess)
sess := newSession(mux, client.cfg.Region)
client.sessionMgr.AddSession(client.cfg.Region, sess)
select {
case <-sess.conn.CloseChan():
break
}
client.sessionMgr.DeleteSession(defaultRegion)
client.sessionMgr.DeleteSession(client.cfg.Region)
logs.Warn("reconnect")
}
}

View File

@@ -3,33 +3,38 @@ package gtun
import (
"io/ioutil"
"github.com/pelletier/go-toml"
"gopkg.in/yaml.v2"
)
type Config struct {
ClientConfig *ClientConfig `toml:"client"`
TCPForward TCPForwardConfig `toml:"tcpforward"`
UDPForward UDPForwardConfig `toml:"udpforward"`
Log Log `toml:"log"`
Forwards map[string]ForwardConfig `yaml:"forwards"`
Log Log `yaml:"log"`
}
type Log struct {
Days int64 `toml:"days"`
Level string `toml:"level"`
Path string `toml:"path"`
type ForwardConfig struct {
ServerAddr string `yaml:"server"`
AuthKey string `yaml:"authKey"`
TCPForward TCPForwardConfig `yaml:"tcp"`
UDPForward UDPForwardConfig `yaml:"udp"`
}
type TCPForwardConfig struct {
ListenAddr string `toml:"listen"`
ReadTimeout int `toml:"readTimeout"`
WriteTimeout int `toml:"writeTimeout"`
ListenAddr string `yaml:"listen"`
ReadTimeout int `yaml:"readTimeout"`
WriteTimeout int `yaml:"writeTimeout"`
}
type UDPForwardConfig struct {
ListenAddr string `toml:"listen"`
ReadTimeout int `toml:"readTimeout"`
WriteTimeout int `toml:"writeTimeout"`
SessionTimeout int `toml:"sessionTimeout"`
ListenAddr string `yaml:"listen"`
ReadTimeout int `yaml:"readTimeout"`
WriteTimeout int `yaml:"writeTimeout"`
SessionTimeout int `yaml:"sessionTimeout"`
}
type Log struct {
Days int64 `yaml:"days"`
Level string `yaml:"level"`
Path string `yaml:"path"`
}
func ParseConfig(path string) (*Config, error) {
@@ -43,6 +48,6 @@ func ParseConfig(path string) (*Config, error) {
func parseConfig(content []byte) (*Config, error) {
conf := Config{}
err := toml.Unmarshal(content, &conf)
err := yaml.Unmarshal(content, &conf)
return &conf, err
}

View File

@@ -18,7 +18,8 @@ func Main() {
}
logs.Init(conf.Log.Path, conf.Log.Level, conf.Log.Days)
tcpfw := NewTCPForward(conf.TCPForward)
for region, cfg := range conf.Forwards {
tcpfw := NewTCPForward(region, cfg.TCPForward)
lis, err := tcpfw.Listen()
if err != nil {
logs.Error("listen tproxy tcp fail: %v", err)
@@ -27,7 +28,7 @@ func Main() {
go tcpfw.Serve(lis)
udpfw := NewUDPForward(conf.UDPForward)
udpfw := NewUDPForward(region, cfg.UDPForward)
udpConn, err := udpfw.Listen()
if err != nil {
logs.Error("listen tproxy udp fail: %v", err)
@@ -36,6 +37,13 @@ func Main() {
go udpfw.Serve(udpConn)
client := NewClient(conf.ClientConfig)
client.Run()
client := NewClient(&ClientConfig{
ServerAddr: cfg.ServerAddr,
AuthKey: cfg.AuthKey,
Region: region,
})
go client.Run()
}
select {}
}

View File

@@ -16,6 +16,7 @@ var (
)
type TCPForward struct {
region string
listenAddr string
// writeTimeout defines the tcp connection write timeout in second
// default value set to 10 seconds
@@ -30,7 +31,7 @@ type TCPForward struct {
sessMgr *SessionManager
}
func NewTCPForward(cfg TCPForwardConfig) *TCPForward {
func NewTCPForward(region string, cfg TCPForwardConfig) *TCPForward {
tcpReadTimeout := cfg.ReadTimeout
if tcpReadTimeout <= 0 {
tcpReadTimeout = defaultTCPTimeout
@@ -41,6 +42,7 @@ func NewTCPForward(cfg TCPForwardConfig) *TCPForward {
tcpWriteTimeout = int(defaultTCPTimeout)
}
return &TCPForward{
region: region,
listenAddr: cfg.ListenAddr,
writeTimeout: time.Duration(tcpWriteTimeout) * time.Second,
readTimeout: time.Duration(tcpReadTimeout) * time.Second,
@@ -89,7 +91,7 @@ func (f *TCPForward) forwardTCP(conn net.Conn) {
dip, dport, _ := net.SplitHostPort(conn.LocalAddr().String())
sip, sport, _ := net.SplitHostPort(conn.RemoteAddr().String())
sess := f.sessMgr.GetSession(defaultRegion)
sess := f.sessMgr.GetSession(f.region)
if sess == nil {
logs.Error("no route to host: %s", dip)
return

View File

@@ -29,6 +29,7 @@ type udpSession struct {
}
type UDPForward struct {
region string
listenAddr string
sessionTimeout int
readTimeout time.Duration
@@ -45,7 +46,7 @@ type UDPForward struct {
udpsessLock sync.Mutex
}
func NewUDPForward(cfg UDPForwardConfig) *UDPForward {
func NewUDPForward(region string, cfg UDPForwardConfig) *UDPForward {
readTimeout := cfg.ReadTimeout
if readTimeout <= 0 {
readTimeout = defaultUDPTimeout
@@ -62,6 +63,7 @@ func NewUDPForward(cfg UDPForwardConfig) *UDPForward {
}
return &UDPForward{
region: region,
listenAddr: cfg.ListenAddr,
readTimeout: time.Duration(readTimeout) * time.Second,
writeTimeout: time.Duration(writeTimeout) * time.Second,
@@ -154,7 +156,7 @@ func (f *UDPForward) Serve(lconn *net.UDPConn) error {
f.udpsessLock.Unlock()
} else {
f.udpsessLock.Unlock()
sess := f.sessMgr.GetSession(defaultRegion)
sess := f.sessMgr.GetSession(f.region)
if sess == nil {
logs.Error("no route to host: %s", dip)
continue

View File

@@ -4,18 +4,18 @@ import (
"encoding/json"
"io/ioutil"
"github.com/pelletier/go-toml"
"gopkg.in/yaml.v2"
)
type Config struct {
ServerConfig ServerConfig `toml:"server"` // tcp server configuration
Log Log `toml:"log"`
ServerConfig ServerConfig `yaml:"server"`
Log Log `yaml:"log"`
}
type Log struct {
Days int64 `toml:"days"`
Level string `toml:"level"`
Path string `toml:"path"`
Days int64 `yaml:"days"`
Level string `yaml:"level"`
Path string `yaml:"path"`
}
func ParseConfig(path string) (*Config, error) {
@@ -29,7 +29,7 @@ func ParseConfig(path string) (*Config, error) {
func parseConfig(content []byte) (*Config, error) {
var c Config
err := toml.Unmarshal(content, &c)
err := yaml.Unmarshal(content, &c)
return &c, err
}

View File

@@ -21,7 +21,7 @@ var (
type ServerConfig struct {
Listen string `toml:"listen"`
AuthKey string `toml:"auth_key"`
AuthKey string `toml:"authKey"`
}
type Server struct {

View File

@@ -7,18 +7,9 @@ mkdir -p bin/gtund
mkdir -p bin/gtund/log
GOOS=linux go build -o bin/gtund/gtund cmd/gtund/*.go
cp etc/gtund.conf bin/gtund/
cp etc/gtund.yaml bin/gtund/
cd cmd/gtun
echo "building gtun_cli_darwin...."
GOOS=darwin go build -o ../../bin/gtun/gtun-darwin_amd64
echo "builded gtun_cli_darwin...."
echo "building gtun_cli_linux...."
GOOS=linux go build -o ../../bin/gtun/gtun-linux_amd64
echo "builded gtun_cli_linux...."
echo "building gtun_cli_win...."
GOOS=windows go build -o ../../bin/gtun/gtun-windows_amd64.exe
echo "builded gtun_cli_win...."

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB