first commit
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,6 +6,8 @@
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
simple-tcp-proxy
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
|
||||
124
simple-tcp-proxy.go
Normal file
124
simple-tcp-proxy.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type TcpListen struct {
|
||||
Listen string `json:"listen"`
|
||||
Backend string `json:"backend"`
|
||||
}
|
||||
|
||||
type TcpListenConfig struct {
|
||||
TcpListens []TcpListen `json:"tcpListens"`
|
||||
}
|
||||
|
||||
// {
|
||||
// "tcpListens": [
|
||||
// "listen": ":8080",
|
||||
// "backend": "11.22.33.44:8080"
|
||||
// ]
|
||||
// }
|
||||
// https://blog.csdn.net/fyxichen/article/details/51505542
|
||||
func main() {
|
||||
|
||||
tcpListenConfig, err := readConfigFile()
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error in load config file: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(tcpListenConfig.TcpListens) == 0 {
|
||||
fmt.Println("Not find any mapping in config")
|
||||
return
|
||||
}
|
||||
|
||||
for _, tcpListen := range tcpListenConfig.TcpListens {
|
||||
go server(tcpListen)
|
||||
}
|
||||
ExitChan := make(chan bool, 1)
|
||||
<-ExitChan
|
||||
}
|
||||
|
||||
func server(tcpListen TcpListen) {
|
||||
lis, err := net.Listen("tcp", tcpListen.Listen)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
defer lis.Close()
|
||||
fmt.Printf("Listen TCP at: %v --> %v\n", tcpListen.Listen, tcpListen.Backend)
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
fmt.Printf("Listen error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("TCP connection from %v, local: %v\n", conn.RemoteAddr(), conn.LocalAddr())
|
||||
go handle(tcpListen, conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handle(tcpListen TcpListen, sconn net.Conn) {
|
||||
defer sconn.Close()
|
||||
ip := tcpListen.Backend
|
||||
dconn, err := net.Dial("tcp", ip)
|
||||
if err != nil {
|
||||
fmt.Printf("Connect to %v failed:%v\n", ip, err)
|
||||
return
|
||||
}
|
||||
ExitChan := make(chan bool, 1)
|
||||
go func(sconn net.Conn, dconn net.Conn, Exit chan bool) {
|
||||
_, err := io.Copy(dconn, sconn)
|
||||
if err != nil {
|
||||
errStr := fmt.Sprintf("%v", err)
|
||||
if strings.Contains(errStr, "use of closed network connection") {
|
||||
fmt.Printf("Connection closed: %v\n", ip)
|
||||
} else {
|
||||
fmt.Printf("Send data to %v failed:%v\n", ip, err)
|
||||
}
|
||||
}
|
||||
ExitChan <- true
|
||||
}(sconn, dconn, ExitChan)
|
||||
go func(sconn net.Conn, dconn net.Conn, Exit chan bool) {
|
||||
_, err := io.Copy(sconn, dconn)
|
||||
if err != nil {
|
||||
errStr := fmt.Sprintf("%v", err)
|
||||
if strings.Contains(errStr, "use of closed network connection") {
|
||||
fmt.Printf("Connection closed: %v\n", ip)
|
||||
} else {
|
||||
fmt.Printf("Receive data from %v failed:%v\n", ip, err)
|
||||
}
|
||||
}
|
||||
ExitChan <- true
|
||||
}(sconn, dconn, ExitChan)
|
||||
<-ExitChan
|
||||
dconn.Close()
|
||||
}
|
||||
|
||||
func readConfigFile() (*TcpListenConfig, error) {
|
||||
configFile, err := os.Open("tcp_listen_config.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer configFile.Close()
|
||||
|
||||
configFileBytes, err := ioutil.ReadAll(configFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var tcpListenConfig TcpListenConfig
|
||||
err = json.Unmarshal(configFileBytes, &tcpListenConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &tcpListenConfig, nil
|
||||
}
|
||||
8
tcp_listen_config.json
Normal file
8
tcp_listen_config.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"tcpListens": [
|
||||
{
|
||||
"listen": ":8443",
|
||||
"backend": "101.132.122.240:443"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user