Skip to content

Commit 380791e

Browse files
author
ying32
committed
首次提交
1 parent 45960d1 commit 380791e

File tree

8 files changed

+332
-0
lines changed

8 files changed

+332
-0
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,17 @@
11
# ReverseProxy
22
简单的反向代理用于内网穿透
3+
4+
最近周末闲来无事,想起了做下微信公共号的开发,但微信限制只能80端口的,自己用的城中村的那种宽带,共用一个公网,没办法自己用路由做端口映射。自己的服务器在腾讯云上,每次都要编译完后用ftp上传再进行调试,非常的浪费时间。 一时间又不知道上哪找一个符合我的这种要求的工具,就索性自己构思了下,整个工作流程大致为:
5+
6+
> 外部请求自己服务器上的HTTP服务端 -> 将数据传递给Socket服务器 -> Socket服务器将数据发送至已连接的Socket客户端 -> Socket客户端收到数据 -> 使用http请求本地http服务端 -> 本地http服务端处理相关后返回 -> Socket客户端将返回的数据发送至Socket服务端 -> Socket服务端解析出数据后原路返回至外部请求的HTTP
7+
8+
**不过目前不支持Cookie与Header的设置,只保留了Method, URL, Body段的数据**
9+
10+
> 使用方法:go get github.com/ying32/ReverseProxy
11+
> 1、分别编译**RServer****RClient**
12+
> 2、在RServer目录下的runsvr.bat或者runsvr.sh修改为你想要的端口后启动并执行。
13+
> 3、在RClient目录下的runcli_local.bat或者runcli_local.sh修改为你想要的端口后启动并执行。
14+
15+
**两个程序总共不到300行的代码量。简单是简单了点,但还是能用用的**
16+
17+
##### 支持Win32, Win64, Linux32, Linux64, MacOSX32, MacOSX64等,无第三方依赖库。

RPClient/client.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"errors"
7+
"flag"
8+
"fmt"
9+
"io/ioutil"
10+
"net"
11+
"net/http"
12+
)
13+
14+
var (
15+
serverAddr = flag.String("addr", "", "连接服务器的地址,如:127.0.0.1:82")
16+
httpProtocol = flag.String("protocol", "http", "服务器的协议,可选为http、https")
17+
httpPort = flag.Int("port", 0, "要求服务端开启转发的端口,只作参考,不强制要求")
18+
localhttpPort = flag.Int("localport", 0, "要转发至本地的http端口,不填或者错误端口号则跟httpPort一致!")
19+
)
20+
21+
func main() {
22+
flag.Parse()
23+
if *httpProtocol != "http" && *httpProtocol != "https" {
24+
fmt.Println("http协议错误!")
25+
return
26+
}
27+
if *serverAddr == "" {
28+
fmt.Println("请输入服务器的地址!")
29+
return
30+
}
31+
if *localhttpPort <= 0 || *localhttpPort >= 65536 {
32+
fmt.Println("端口配置范围错误!")
33+
return
34+
}
35+
36+
fmt.Println("信息:本次要求服务器开启:", *httpPort, "号端口,将被转发至本地:", *localhttpPort, "端口,使用协议为:", *httpProtocol)
37+
conn, err := net.Dial("tcp", *serverAddr)
38+
if err != nil {
39+
fmt.Println("连接服务端失败:", err.Error())
40+
return
41+
}
42+
defer conn.Close()
43+
StartClient(conn)
44+
}
45+
46+
func StartClient(conn net.Conn) {
47+
fmt.Println("已成功连接服务端!地址:", *serverAddr)
48+
val := make([]byte, 4)
49+
for {
50+
_, err := conn.Read(val)
51+
if err != nil {
52+
fmt.Println("读取服务器数据异常:", err.Error())
53+
break
54+
}
55+
if string(val) == "sign" {
56+
c, err := conn.Read(val)
57+
if err == nil && c == 4 {
58+
bs := bytes.NewBuffer(val)
59+
var bodylen int32
60+
binary.Read(bs, binary.LittleEndian, &bodylen)
61+
fmt.Println("服务端发送数据长为:", bodylen)
62+
if bodylen > 0 {
63+
bs := make([]byte, bodylen)
64+
c, err := conn.Read(bs)
65+
if err == nil && c == int(bodylen) {
66+
if err = httpMethod(bs, conn); err != nil {
67+
fmt.Println("httpMethod请求错误:", err)
68+
conn.Write([]byte("msg0"))
69+
}
70+
} else {
71+
fmt.Println("读取数据长错误:", err)
72+
}
73+
}
74+
}
75+
} else if string(val) == "msg0" {
76+
fmt.Println("服务器配置错误,消息懒得读了")
77+
return
78+
} else {
79+
fmt.Println("读取签名错误!")
80+
}
81+
}
82+
}
83+
84+
// 请求的方法
85+
func httpMethod(data []byte, conn net.Conn) error {
86+
if len(data) == 0 {
87+
return errors.New("无数据可用")
88+
}
89+
reader := bytes.NewReader(data)
90+
// 读取Method
91+
var nlen int32 = 0
92+
binary.Read(reader, binary.LittleEndian, &nlen)
93+
if nlen == 0 || nlen > 10 {
94+
return errors.New("Method数据长度错误!")
95+
}
96+
mbytes := make([]byte, nlen)
97+
binary.Read(reader, binary.LittleEndian, &mbytes)
98+
method := string(mbytes)
99+
100+
// 读取请求的url
101+
nlen = 0
102+
binary.Read(reader, binary.LittleEndian, &nlen)
103+
if nlen == 0 || nlen > 1024 {
104+
return errors.New("URL数据长度错误!")
105+
}
106+
mbytes = make([]byte, nlen)
107+
binary.Read(reader, binary.LittleEndian, &mbytes)
108+
url := string(mbytes)
109+
// 读取body的数据
110+
var contentlen int64
111+
binary.Read(reader, binary.LittleEndian, &contentlen)
112+
body := bytes.NewBuffer([]byte{})
113+
if contentlen > 0 {
114+
mbytes = make([]byte, contentlen)
115+
binary.Read(reader, binary.LittleEndian, mbytes)
116+
binary.Write(body, binary.LittleEndian, mbytes)
117+
}
118+
req, err := http.NewRequest(method, fmt.Sprintf("%s://127.0.0.1:%d%s", *httpProtocol, *localhttpPort, url), body)
119+
if err != nil {
120+
return err
121+
}
122+
defer req.Body.Close()
123+
client := new(http.Client)
124+
resp, err := client.Do(req)
125+
if err != nil {
126+
return err
127+
}
128+
defer resp.Body.Close()
129+
retbytes, err := ioutil.ReadAll(resp.Body)
130+
if err != nil {
131+
return err
132+
}
133+
sendio := bytes.NewBuffer([]byte{})
134+
// 写签名
135+
binary.Write(sendio, binary.LittleEndian, []byte("sign"))
136+
// 写长度
137+
binary.Write(sendio, binary.LittleEndian, int32(len(retbytes)))
138+
// 写数据
139+
binary.Write(sendio, binary.LittleEndian, retbytes)
140+
141+
if n, err := conn.Write(sendio.Bytes()); n == sendio.Len() && err == nil {
142+
fmt.Println("回复成功!")
143+
return nil
144+
} else {
145+
return err
146+
}
147+
}

RPClient/runcli_local.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
RPClient --addr="127.0.0.1:8284" --protocol="http" --localport=8085 --port=8084

RPClient/runcli_local.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./RPClient --addr="127.0.0.1:8284" --protocol="http" --localport=8085 --port=8084

RPServer/runsvr.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
RPServer --port=8284 --httpport=8084

RPServer/runsvr.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./RPServer --port=8284 --httpport=8084

RPServer/server.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"flag"
7+
"fmt"
8+
"io/ioutil"
9+
"net"
10+
"net/http"
11+
"time"
12+
)
13+
14+
var (
15+
tcpPort = flag.Int("port", 0, "TCP监听的端口")
16+
httpPort = flag.Int("httpport", 0, "监听的http端口")
17+
)
18+
19+
var (
20+
clientConn *net.TCPConn
21+
)
22+
23+
func main() {
24+
flag.Parse()
25+
if *tcpPort <= 0 || *httpPort >= 65536 {
26+
fmt.Println("请输入一个正确的TCP端口")
27+
return
28+
}
29+
if *httpPort <= 0 || *httpPort >= 65536 {
30+
fmt.Println("请输入一个正确的HTTP端口")
31+
}
32+
fmt.Println("监听服务端监端口:", *tcpPort)
33+
listen, err := net.ListenTCP("tcp", &net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: *tcpPort, Zone: ""})
34+
if err != nil {
35+
fmt.Println(err)
36+
return
37+
}
38+
defer listen.Close()
39+
go startHttpServer(*httpPort)
40+
fmt.Println("正在进行TCP连接监听...")
41+
startServer(listen)
42+
}
43+
44+
func startServer(l *net.TCPListener) {
45+
for {
46+
conn, err := l.AcceptTCP()
47+
// 一个服务端只对应一个客户端
48+
if err != nil || clientConn != nil {
49+
fmt.Println(err)
50+
conn.Close()
51+
continue
52+
}
53+
// 处理新的连接
54+
fmt.Println("处理新的客户端连接")
55+
go processTCPConn(conn)
56+
}
57+
}
58+
59+
func startHttpServer(port int) {
60+
fmt.Println("开始监听HTTP", port, "端口...")
61+
62+
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
63+
http.Error(w, "Not Found", http.StatusNotFound)
64+
})
65+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
66+
67+
if clientConn != nil {
68+
69+
httpBody := bytes.NewBuffer([]byte{})
70+
// 请求的方法
71+
mBytes := []byte(r.Method)
72+
binary.Write(httpBody, binary.LittleEndian, int32(len(mBytes)))
73+
binary.Write(httpBody, binary.LittleEndian, mBytes)
74+
75+
// 请求的url
76+
mBytes = []byte(r.URL.String())
77+
binary.Write(httpBody, binary.LittleEndian, int32(len(mBytes)))
78+
binary.Write(httpBody, binary.LittleEndian, mBytes)
79+
// 如果是IO数据
80+
binary.Write(httpBody, binary.LittleEndian, r.ContentLength)
81+
if r.ContentLength > 0 {
82+
bs, _ := ioutil.ReadAll(r.Body)
83+
binary.Write(httpBody, binary.LittleEndian, bs)
84+
}
85+
86+
sendio := bytes.NewBuffer([]byte{})
87+
binary.Write(sendio, binary.LittleEndian, []byte("sign"))
88+
binary.Write(sendio, binary.LittleEndian, int32(httpBody.Len()))
89+
binary.Write(sendio, binary.LittleEndian, httpBody.Bytes())
90+
91+
mBytes = sendio.Bytes()
92+
fmt.Println("输出:", string(mBytes))
93+
94+
if nlen, err := clientConn.Write(mBytes); len(mBytes) != nlen || err != nil {
95+
fmt.Println("发送错误:已发送:", nlen, "字节, 错误消息:", err)
96+
} else {
97+
fmt.Println("本次发送成功!共:", nlen, "个字节")
98+
}
99+
100+
if clientConn != nil {
101+
102+
val := make([]byte, 4)
103+
_, err := clientConn.Read(val)
104+
flags := string(val)
105+
if err == nil && flags == "sign" {
106+
c, err := clientConn.Read(val)
107+
if err == nil && c == 4 {
108+
bs := bytes.NewBuffer(val)
109+
var bodylen int32
110+
binary.Read(bs, binary.LittleEndian, &bodylen)
111+
if bodylen > 0 {
112+
bs := make([]byte, bodylen)
113+
if c, err := clientConn.Read(bs); err == nil && c == int(bodylen) {
114+
w.Write(bs)
115+
return
116+
}
117+
}
118+
}
119+
} else if flags == "msg0" {
120+
fmt.Println("客户端http请求返回失败!")
121+
}
122+
}
123+
}
124+
w.Write([]byte(""))
125+
})
126+
if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
127+
fmt.Println("http服务端错误,消息:", err)
128+
return
129+
}
130+
fmt.Println("HTTP服务结束。")
131+
}
132+
133+
func processTCPConn(conn *net.TCPConn) {
134+
conn.SetKeepAlive(true)
135+
conn.SetKeepAlivePeriod(time.Duration(10 * time.Second))
136+
defer conn.Close()
137+
clientConn = conn
138+
test := make([]byte, 0)
139+
for {
140+
_, err := clientConn.Read(test)
141+
if err != nil {
142+
fmt.Println("客户端断开连接! ")
143+
break
144+
}
145+
time.Sleep(time.Duration(time.Second * 3))
146+
}
147+
clientConn = nil
148+
fmt.Println("客户端已经退出!")
149+
}

Sample/sample.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
)
7+
8+
func main() {
9+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
10+
fmt.Println("服务端请求数据了!")
11+
w.Write([]byte("请求成功!"))
12+
})
13+
fmt.Println("监听HTTP 8085端口中...")
14+
if err := http.ListenAndServe(":8085", nil); err != nil {
15+
fmt.Println("服务器开启失败")
16+
}
17+
}

0 commit comments

Comments
 (0)