目录
- 这是一个演示
- 主要分为俩包:
- 流程:
- 逻辑:(端口随意,本地ssh为例)
- 用法:
- 文件地址:
- 代码如下:
这是一个演示
代理本地HTTP服务
代理局域网SSH服务
其他的TCP服务没测试了
主要分为俩包:
main -》 主函数,包含Server、Client函数和goroutine函数
utils -》 工具函数,包含发包和读包函数,现在使用的是json序列化没有加密(内置AES256加密,可以把粘包问题处理后进行使用)
流程:
返回数据呈现给用户:
本地Conn -》服务器中转Conn -》 服务器代理Conn
用户发送请求到本地:
服务器代理Conn -》 本地中转Conn -》 本地Conn
逻辑:(端口随意,本地ssh为例)
- Server (对外IP 1.2.3.4)
- 先监听0.0.0.0:2222(中转代理服务)
- 有连接 -》进行②
- 无连接 -》 继续听(每隔5秒)
- 再监听0.0.0.0:3333(代理出来的端口)
- 先监听0.0.0.0:2222(中转代理服务)
- Client
- 先连接127.0.0.1:22(本地服务)(这两个先后顺序无所谓)
- 成功 -》进行②
- 失败-》 继续连(每隔5秒)
- 再连接1.2.3.4:2222(中转代理服务)
- 先连接127.0.0.1:22(本地服务)(这两个先后顺序无所谓)
用法:
使用方法:
服务器模式:
程序名 -s R1地址:端口 Up地址:端口
例子:程序名 -s x.x.x.x:2222 x.x.x.x:3333
客户端模式:
程序名 -c 本地地址:端口 R1地址:端口
例子:程序名 -c 127.0.0.1:22 x.x.x.x:2222
显示帮助信息:
程序名 -h
文件地址:
Github地址:https://github.com/jumppppp/go/tree/master/htools/pangolin
代码如下:
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"net"
"pangolin/utils"
"time"
)
type Client_t struct{
ConnLocal net.Conn
BufR1 [1024]byte
ConnR1 net.Conn
ConnectedR1 bool
}
type Server_t struct{
LnR1 net.Listener
ConnR1 net.Conn
ConnectedUp bool
LnUp net.Listener
ConnUp net.Conn
BufR1 [1024]byte
}
func printUsage() {
fmt.Println("使用方法:")
fmt.Println("服务器模式:")
fmt.Println(" 程序名 -s R1地址:端口 Up地址:端口")
fmt.Println(" 例子:程序名 -s x.x.x.x:2222 x.x.x.x:3333")
fmt.Println("客户端模式:")
fmt.Println(" 程序名 -c 本地地址:端口 R1地址:端口")
fmt.Println(" 例子:程序名 -c 127.0.0.1:22 x.x.x.x:2222")
fmt.Println("显示帮助信息:")
fmt.Println(" 程序名 -h")
}
func main() {
var (
helpFlag bool
serverFlag bool
clientFlag bool
)
// 设置命令行参数
flag.BoolVar(&helpFlag, "h", false, "显示帮助信息")
flag.BoolVar(&serverFlag, "s", false, "使用服务器模式")
flag.BoolVar(&clientFlag, "c", false, "使用客户端模式")
flag.Parse()
if helpFlag {
printUsage()
return
}
args := flag.Args()
if serverFlag {
if len(args) != 2 {
fmt.Println("错误:请提供R1地址和Up地址")
printUsage()
return
}
HpR1 := args[0]
HpUp := args[1]
Server(HpR1, HpUp)
} else if clientFlag {
if len(args) != 2 {
fmt.Println("错误:请提供本地地址和R1地址")
printUsage()
return
}
HpLocal := args[0]
HpR1 := args[1]
Client(HpR1, HpLocal)
} else {
fmt.Println("错误:请提供-s或-c选项")
printUsage()
}
}
func Server(HpR1 string,HpUp string)(){
ms:=&Server_t{}
var err error
ms.LnR1,err = net.Listen("tcp",HpR1)
if err!=nil{
fmt.Println("远程服务R1 No=",err)
}
fmt.Println("远程服务R1...")
ms.LnUp,err = net.Listen("tcp",HpUp)
if err!=nil{
fmt.Println("远程服务Up No=",err)
}
fmt.Println("远程服务Up...")
go ms.handleServerR1()
ms.handleServerUp()
}
func (this * Server_t)handleServerR1()(){
var err error
for{
this.ConnR1,err = this.LnR1.Accept()
if err != nil {
fmt.Println("Accept error:", err)
continue // 继续等待下一个连接请求
}
fmt.Println(this.ConnR1.RemoteAddr().String()," Connect ",this.ConnR1.LocalAddr().String())
for{
tf := &utils.Transfer{Conn: this.ConnR1,}
data,err,offset,data2:=tf.ReadPkgNo()
if err!=nil{
fmt.Println("R R1 No=",err)
if err == io.EOF { // 远程主机已经关闭连接
fmt.Println("Connection closed by remote host")
}
break
}
switch data.Type{
case utils.BackType:
// fmt.Println(data)
for {
if this.ConnectedUp{
this.ConnUp.Write(data.Data)
if offset!=0{
this.ConnUp.Write(data2.Data)
}
break
}else{
fmt.Println("未检测到Up连接 等待5秒")
time.Sleep(5*time.Second)
}
}
case utils.GoType:
fmt.Println(data)
default:
fmt.Println(data)
}
}
this.ConnR1.Close() // 关闭连接
}
}
func (this * Server_t)handleServerUp()(){
var err error
for {
this.ConnUp, err = this.LnUp.Accept()
if err != nil {
fmt.Println("Accept error:", err)
continue // 继续等待下一个连接请求
}
fmt.Println(this.ConnUp.RemoteAddr().String(), " Connect ", this.ConnUp.LocalAddr().String())
this.ConnectedUp = true
for {
n, err := this.ConnUp.Read(this.BufR1[:])
if err != nil {
fmt.Println("R Up No", err)
if err == io.EOF { // 远程主机已经关闭连接
fmt.Println("Connection closed by remote host")
}
this.ConnectedUp = false
break // 退出当前循环并关闭连接
}
tf:=&utils.Transfer{Conn: this.ConnR1,}
//发送返回包
var GoMsg utils.Message
GoMsg.Type = utils.GoType
GoMsg.Data = this.BufR1[:n]
GoMsgM,err:=json.Marshal(GoMsg)
if err!=nil{
fmt.Println("No=",err)
}
err = tf.WritePkgNo(GoMsgM)
if err!=nil{
fmt.Println("WNo=",err)
}
for i := range this.BufR1 {
this.BufR1[i] = 0
}
}
this.ConnUp.Close() // 关闭连接
}
}
func Client(HpR1 string,HpLocal string)(){
mc:=&Client_t{}
go mc.handleR1(HpR1)
mc.handleLocal(HpLocal)
}
func (this * Client_t)handleLocal(hp string){
//做最大次数尝试
var err error
for{
this.ConnLocal,err = net.Dial("tcp",hp)
if err!=nil{
fmt.Println("本地服务连接No=",err)
}
fmt.Println("本地服务已连接")
for{
n,err := this.ConnLocal.Read(this.BufR1[:])
if err!=nil{
fmt.Println("R Local No=",err)
if err == io.EOF { // 远程主机已经关闭连接
fmt.Println("Connection closed by remote host")
}
break
}
if this.ConnectedR1{
tf:=&utils.Transfer{Conn: this.ConnR1,}
//发送返回包
var BackMsg utils.Message
BackMsg.Type = utils.BackType
BackMsg.Data = this.BufR1[:n]
BackMsgM,err:=json.Marshal(BackMsg)
if err!=nil{
fmt.Println("No=",err)
}
fmt.Println("读到",n,"发送",len(BackMsgM))
err = tf.WritePkgNo(BackMsgM)
if err!=nil{
fmt.Println("WNo=",err)
}
for i := range this.BufR1 {
this.BufR1[i] = 0
}
}else{
fmt.Println("未检测到R1连接 等待5秒")
time.Sleep(5*time.Second)
}
}
this.ConnLocal.Close()
}
}
func (this * Client_t)handleR1(hp string){
// defer HR.Done()
var err error
for{
this.ConnR1,err = net.Dial("tcp",hp)
if err!=nil{
fmt.Println("远程服务R1 等待5秒 No=",err)
time.Sleep(5*time.Second)
continue
}
fmt.Println("远程服务已连接")
this.ConnectedR1 = true
for{
tf := &utils.Transfer{Conn: this.ConnR1,}
data,err,offset,data2:=tf.ReadPkgNo()
if err!=nil{
fmt.Println("R R1 No=",err)
if err == io.EOF { // 远程主机已经关闭连接
fmt.Println("Connection closed by remote host")
}
this.ConnectedR1 = false
break
}
switch data.Type{
case utils.BackType:
fmt.Println(data)
case utils.GoType:
// fmt.Println(data)
this.ConnLocal.Write(data.Data)
if offset!=0{
this.ConnLocal.Write(data2.Data)
}
default:
fmt.Println(data)
}
}
this.ConnR1.Close()
}
}
package utils
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"net"
)
var (
GoType string ="Go"
BackType string = "Back"
)
type Message struct{
Type string `json:"type"`
Data []byte `json:"data"`
}
type Transfer struct{
Conn net.Conn //文件描述符
Buf [4096]byte //缓冲
}
func (this *Transfer)WritePkgNo(data []byte) (err error) {
pkgLen := uint32(len(data))
binary.BigEndian.PutUint32(this.Buf[:4], pkgLen)
n := copy(this.Buf[4:], data)
if n!=int(pkgLen){
fmt.Println("Copy No=",n,"!=",int(pkgLen))
return
}
lastLen :=int(pkgLen)+4
// fmt.Println("W=",this.Buf[:4],string(this.Buf[4:lastLen]),int(pkgLen),string(data))
fmt.Println("W=",int(pkgLen))
n,err=this.Conn.Write(this.Buf[:lastLen])
if err!=nil || int(lastLen)!=n{
fmt.Println(err,int(lastLen),"!=",n)
return
}
return
}
func (this *Transfer)ReadPkgNo()(msg Message,err error,offset int,msg2 Message){
n,err:=this.Conn.Read(this.Buf[:])
if err!=nil{
fmt.Println("R No=",err)
return
}
var pkgLen uint32
pkgLen = binary.BigEndian.Uint32(this.Buf[:4])
lastLen:=int(pkgLen)+4
// fmt.Println("R=",this.Buf[:4],string(this.Buf[4:lastLen]),int(pkgLen),string(this.Buf[4:n]))
fmt.Println("W=",int(pkgLen))
if n!=lastLen{
fmt.Println("[1]",int(lastLen),"!=",n)
offset = lastLen
var pkgLen2 uint32
pkgLen2 = binary.BigEndian.Uint32(this.Buf[offset:offset+4])
if n!= offset+4+int(pkgLen2){
fmt.Println("[2]",int(offset+4+int(pkgLen2)),"!=",n)
}
err = json.Unmarshal(this.Buf[offset+4:offset+4+int(pkgLen2)],&msg2)
if err!=nil{
fmt.Println("Unmarshal No=",err)
return
}
fmt.Println("第二个包",msg2)
}else{
offset = 0
}
err = json.Unmarshal(this.Buf[4:lastLen],&msg)
if err!=nil{
fmt.Println("Unmarshal No=",err)
return
}
return
}
func (this *Transfer)WritePkg(data []byte) (err error) {
//加密流程,长度+原始内容 -》 替换过的密钥(32)+长度(4)+加密内容
pkgLen := uint32(len(data))
fmt.Println("write n=",int(pkgLen))
var BufTemp [4096]byte
binary.BigEndian.PutUint32(BufTemp[:4], pkgLen)
n := copy(BufTemp[4:], data)
if n!=int(pkgLen){
fmt.Println("WNo=",n,"!=",int(pkgLen))
return
}
lastLenTemp := 4+n
// fmt.Println(string(BufTemp[:]))
//加密程序
oldKey,newKey:= OutKey()
// fmt.Println(string(oldKey),len(oldKey),string(newKey),len(newKey))
ciphertext, err := EncryptAES(BufTemp[:lastLenTemp],[]byte(oldKey))
if err != nil {
fmt.Println("EncodeNo=",err)
return
}
EnpkgLen := uint32(len(ciphertext))
binary.BigEndian.PutUint32(this.Buf[32:36], EnpkgLen)
copy(this.Buf[:32], newKey)
n =copy(this.Buf[36:],ciphertext)
lastLen := 36+n
// fmt.Println(string(this.Buf[:32]),this.Buf[32:36],this.Buf[36:lastLen])
//发包
n, err = this.Conn.Write(this.Buf[:lastLen])
if err != nil || n!=int(lastLen) {
fmt.Println("WNo=", err,n,"!=",int(lastLen))
return
}
//调试
// fmt.Println("W=",this.Buf[:4],string(this.Buf[4:lastLen]),"n=",n)
return
}
func (this *Transfer)ReadPkg()(msg Message,err error){
//解密流程,替换过的密钥(32)+长度(4)+加密内容 -》 长度+原始内容
//fmt.Println("Reading client send message...")
n,err:=this.Conn.Read(this.Buf[:])
if err!=nil{
return
}
if n<=32{
err = fmt.Errorf("The Readpkg is Null %v %v %v %v",string(this.Buf[:n]),this.Buf[:n],this.Conn.RemoteAddr().String(),this.Conn.LocalAddr().String())
return
}
var EnpkgLen uint32
EnpkgLen = binary.BigEndian.Uint32(this.Buf[32:36])
newKey := string(this.Buf[:32])
oldKey := KeyOut(newKey)
// fmt.Println(newKey,oldKey,EnpkgLen)
EncodeData := this.Buf[36:36+EnpkgLen]
// fmt.Println(EncodeData)
// decrypt ciphertext with AES-256-CBC
decryptedPlaintext, err := DecryptAES(EncodeData, []byte(oldKey))
if err != nil {
fmt.Println("DecodeNo=",err)
return
}
n = copy(this.Buf[:],decryptedPlaintext)
// fmt.Println(string(decryptedPlaintext),n)
//调试
var pkgLen uint32
pkgLen = binary.BigEndian.Uint32(this.Buf[:4])
//调试
fmt.Println("read n=",int(pkgLen))
// fmt.Println("R=",this.Buf[:4],string(this.Buf[4:n]),"n=",n)
if err!=nil||(n-4)!=int(pkgLen){
fmt.Println("RNo=",err,(n-4),"!=",int(pkgLen))
return
}
//调试
err = json.Unmarshal(this.Buf[4:n],&msg)
if err!=nil{
fmt.Println("No=",err)
}
return
}
func OutKey() (oldKey string, newKey string) {
// 生成32字节的随机密钥
key := make([]byte, 16)
if _, err := rand.Read(key); err != nil {
panic(err)
}
oldKey = hex.EncodeToString(key)
// 转换为16进制字符串并替换字符
replacementMap := map[rune]rune{
'0': 'f',
'1': 'e',
'2': 'd',
'3': 'c',
'4': 'b',
'5': 'a',
'6': '9',
'7': '8',
'8': '7',
'9': '6',
'a': '5',
'b': '4',
'c': '3',
'd': '2',
'e': '1',
'f': '0',
}
var buffer bytes.Buffer
for _, r := range oldKey {
if original, ok := replacementMap[r]; ok {
buffer.WriteRune(original)
} else {
buffer.WriteRune(r)
}
}
newKey = buffer.String()
return
}
func KeyOut(hexKey string) string {
// 构造字符替换表
replacementMap := map[rune]rune{
'f': '0',
'e': '1',
'd': '2',
'c': '3',
'b': '4',
'a': '5',
'9': '6',
'8': '7',
'7': '8',
'6': '9',
'5': 'a',
'4': 'b',
'3': 'c',
'2': 'd',
'1': 'e',
'0': 'f',
}
// 转换为字节数组并替换字符
keyBytes, err := hex.DecodeString(hexKey)
if err != nil {
panic(err)
}
var buffer bytes.Buffer
for _, b := range keyBytes {
hexStr := hex.EncodeToString([]byte{b})
rune1 := rune(hexStr[0])
rune2 := rune(hexStr[1])
if original1, ok := replacementMap[rune1]; ok {
buffer.WriteRune(original1)
} else {
buffer.WriteRune(rune1)
}
if original2, ok := replacementMap[rune2]; ok {
buffer.WriteRune(original2)
} else {
buffer.WriteRune(rune2)
}
}
replacedHexKey := buffer.String()
return replacedHexKey
}
// EncryptAES encrypts plaintext using AES-256-CBC with the given key
func EncryptAES(plaintext []byte, key []byte) ([]byte, error) {
// create AES cipher block
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// pad plaintext with PKCS#7 padding
paddedPlaintext := pkcs7Pad(plaintext, aes.BlockSize)
// generate random IV
iv := make([]byte, aes.BlockSize)
if _, err := rand.Read(iv); err != nil {
return nil, err
}
// create CBC mode encrypter
cbc := cipher.NewCBCEncrypter(block, iv)
// encrypt plaintext
ciphertext := make([]byte, len(paddedPlaintext))
cbc.CryptBlocks(ciphertext, paddedPlaintext)
// append IV to the beginning of the ciphertext
ciphertext = append(iv, ciphertext...)
return ciphertext, nil
}
// DecryptAES decrypts ciphertext using AES-256-CBC with the given key
func DecryptAES(ciphertext []byte, key []byte) ([]byte, error) {
if len(ciphertext) < aes.BlockSize*2 {
return nil, errors.New("invalid ciphertext")
}
// extract IV from the beginning of the ciphertext
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
// create AES cipher block
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// create CBC mode decrypter
cbc := cipher.NewCBCDecrypter(block, iv)
// decrypt ciphertext
decryptedPlaintext := make([]byte, len(ciphertext))
cbc.CryptBlocks(decryptedPlaintext, ciphertext)
// unpad plaintext by removing PKCS#7 padding
plaintext, err := pkcs7Unpad(decryptedPlaintext, aes.BlockSize)
if err != nil {
return nil, err
}
return plaintext, nil
}
func pkcs7Pad(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("empty data")
}
if length%blockSize != 0 {
return nil, errors.New("invalid data length")
}
padding := int(data[length-1])
if padding > blockSize || padding == 0 {
return nil, errors.New("invalid padding")
}
for i := 1; i <= padding; i++ {
if data[length-i] != byte(padding) {
return nil, errors.New("invalid padding")
}
}
return data[:length-padding], nil
}
代码还会出现一些问题,粘包问题,不能多个连接等问题