-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from dollarkillerx/dev
Dev
- Loading branch information
Showing
12 changed files
with
986 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Generate: | ||
@echo 'Build GRPC' | ||
protoc -I rpc/proto/ rpc/proto/*.proto --go_out=plugins=grpc:rpc/proto/. | ||
|
||
generate_test: | ||
@echo 'generate_test' | ||
protoc -I test_simple/proto/ test_simple/proto/*.proto --go_out=plugins=grpc:test_simple/proto/. | ||
protoc -I test_stream/proto/ test_stream/proto/*.proto --go_out=plugins=grpc:test_stream/proto/. | ||
|
||
|
||
SSLKey: | ||
@echo 'SSLKey' | ||
openssl genrsa -out cert/server.key 2048 | ||
openssl ecparam -genkey -name secp384r1 -out cert/serveryek | ||
openssl req -new -x509 -sha256 -key cert/serveryek -out cert/servermpe -days 3650 # plumber |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
# plumber | ||
walk in the darkness and worship the light. | ||
|
||
### 测试 | ||
Cloudflase | ||
1. simple | ||
2. stream | ||
|
||
推荐使用Stream | ||
`CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -tags=tcp ` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"crypto/tls" | ||
"crypto/x509" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net" | ||
"os" | ||
"plumber/utils" | ||
"strconv" | ||
|
||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials" | ||
"plumber/rpc" | ||
) | ||
|
||
const pem = ` | ||
-----BEGIN CERTIFICATE----- | ||
MIICYzCCAeqgAwIBAgIUTShO8REvwRrDoBdRq9ZzzcEMP6swCgYIKoZIzj0EAwIw | ||
aTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu | ||
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UECwwHcGx1bWJlcjEQMA4GA1UE | ||
AwwHcGx1bWJlcjAeFw0yMDEwMjcxMTU1MDZaFw0zMDEwMjUxMTU1MDZaMGkxCzAJ | ||
BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l | ||
dCBXaWRnaXRzIFB0eSBMdGQxEDAOBgNVBAsMB3BsdW1iZXIxEDAOBgNVBAMMB3Bs | ||
dW1iZXIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATvf5qn0hKp56iFULTyXfTNRVMf | ||
8mBgQR8GiJlhMNs8SE/128T2lD0UFDMrAVxKxo/rHsP5ORiP/uc9NnK721dVlmcH | ||
40XGXtW2BbThJeCFdNO1ife81fuqzxWx4oSIGWajUzBRMB0GA1UdDgQWBBQoI4sE | ||
Nx8JzONu9VixAeN1Kr5GdzAfBgNVHSMEGDAWgBQoI4sENx8JzONu9VixAeN1Kr5G | ||
dzAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA2cAMGQCMEa8IP5y+EzZOzrm | ||
O9yFZkNqkBkFl00M0GAR5wvO1W6pyC7tJfvgxd8C3mClltakOgIwXzDvpKz9eG4h | ||
59r69pUhx2Jc5ffDO/SbNEx51o3zOvdR77OxaJvNS/cyC2TENO8C | ||
-----END CERTIFICATE----- | ||
` | ||
|
||
// ./client addr socketAddr user passwd | ||
func main() { | ||
//log.SetFlags(log.LstdFlags | log.Llongfile) | ||
if len(os.Args) < 5 { | ||
log.Fatalln("what fuck???") | ||
} | ||
addr, err := net.ResolveTCPAddr("tcp", os.Args[2]) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
l, err := net.ListenTCP("tcp", addr) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
log.Println("Socket Addr: ", os.Args[2]) | ||
s := New(os.Args[1]) | ||
if len(os.Args) > 5 { | ||
s.pac = true | ||
log.Println("Pac Model") | ||
} | ||
|
||
for { | ||
client, err := l.Accept() | ||
if err != nil { | ||
log.Println(err) | ||
continue | ||
} | ||
|
||
go s.handleClientRequest(client) | ||
} | ||
} | ||
|
||
type server struct { | ||
client rpc.PlumberClient | ||
pac bool | ||
} | ||
|
||
func New(addr string) *server { | ||
creds, err := NewClientTLSFromFile(pem, "plumber") | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&loginCreds{ | ||
Username: os.Args[3], | ||
Password: os.Args[4], | ||
})) | ||
|
||
client := rpc.NewPlumberClient(conn) | ||
return &server{client: client} | ||
} | ||
|
||
func (s *server) handleClientRequest(client net.Conn) { | ||
defer func() { | ||
if err := recover(); err != nil { | ||
fmt.Printf("%s\n", err) | ||
return | ||
} | ||
}() | ||
|
||
if client == nil { | ||
return | ||
} | ||
defer client.Close() | ||
var b [1024]byte | ||
n, err := client.Read(b[:]) | ||
if err != nil { | ||
//log.Println(err) | ||
return | ||
} | ||
var pac bool | ||
if b[0] == 0x05 { //只处理Socket5协议 | ||
//客户端回应:Socket服务端不需要验证方式 | ||
client.Write([]byte{0x05, 0x00}) | ||
n, err = client.Read(b[:]) | ||
var host, port string | ||
switch b[3] { | ||
case 0x01: //IP V4 | ||
host = net.IPv4(b[4], b[5], b[6], b[7]).String() | ||
pac, err = s.isPac(host, "") | ||
if err != nil { | ||
//log.Println(err) | ||
return | ||
} | ||
case 0x03: //域名 | ||
host = string(b[5 : n-2]) //b[4]表示域名的长度 | ||
pac, err = s.isPac("", host) | ||
if err != nil { | ||
//log.Println(err) | ||
return | ||
} | ||
case 0x04: //IP V6 | ||
//host = net.IP{b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19]}.String() | ||
return | ||
} | ||
port = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1])) | ||
|
||
addr := net.JoinHostPort(host, port) | ||
|
||
if _, err := client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); err != nil { //响应客户端连接成功 | ||
//log.Println(err) | ||
return | ||
} | ||
|
||
if pac { | ||
simple(client, addr) | ||
return | ||
} | ||
|
||
//进行转发 | ||
stream, err := s.client.Plumber(context.TODO()) | ||
if err != nil { | ||
//log.Println(err) | ||
return | ||
} | ||
|
||
|
||
if err := stream.Send(&rpc.PlumberRequest{ | ||
Addr: addr, | ||
}); err != nil { | ||
//log.Println(err) | ||
return | ||
} | ||
|
||
go copy1(stream, client) | ||
copy2(client, stream) | ||
} | ||
} | ||
|
||
func copy1(server rpc.Plumber_PlumberClient, client io.Reader) { | ||
for { | ||
var b [1024]byte | ||
read, err := client.Read(b[:]) | ||
if err != nil { | ||
if err == io.EOF { | ||
server.Send(&rpc.PlumberRequest{Over: true}) | ||
break | ||
} | ||
break | ||
} | ||
|
||
if err := server.Send(&rpc.PlumberRequest{Data: b[:read]}); err != nil { | ||
//log.Println(err) | ||
break | ||
} | ||
} | ||
} | ||
|
||
func copy2(client io.Writer, server rpc.Plumber_PlumberClient) { | ||
for { | ||
recv, err := server.Recv() | ||
if err != nil { | ||
//log.Println(err) | ||
break | ||
} | ||
if _, err := client.Write(recv.Data); err != nil { | ||
//log.Println(err) | ||
break | ||
} | ||
} | ||
} | ||
|
||
func (s *server) isPac(ip string, domain string) (bool, error) { | ||
if s.pac { | ||
if ip != "" { | ||
search, err := utils.IP2.MemorySearch(ip) | ||
if err != nil { | ||
return false, err | ||
} | ||
if search.Country == "中国" { | ||
return true, nil | ||
} | ||
} | ||
if domain != "" { | ||
lookupIP, err := net.LookupIP(domain) | ||
if err != nil { | ||
return false, err | ||
} | ||
if len(lookupIP) >= 1 { | ||
search, err := utils.IP2.MemorySearch(lookupIP[0].String()) | ||
if err != nil { | ||
return false, err | ||
} | ||
if search.Country == "中国" { | ||
return true, nil | ||
} | ||
} | ||
} | ||
} | ||
return false, nil | ||
} | ||
|
||
func simple(client net.Conn, addr string) { | ||
//log.Println("Simple ", addr) | ||
addrs, err := net.ResolveTCPAddr("tcp", addr) | ||
if err != nil { | ||
return | ||
} | ||
server, err := net.DialTCP("tcp", nil, addrs) | ||
if err != nil { | ||
return | ||
} | ||
|
||
if err := server.SetLinger(0); err != nil { | ||
return | ||
} | ||
|
||
defer server.Close() | ||
//进行转发 | ||
go io.Copy(server, client) | ||
io.Copy(client, server) | ||
} | ||
|
||
type loginCreds struct { | ||
Username, Password string | ||
} | ||
|
||
func (c *loginCreds) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { | ||
return map[string]string{ | ||
"username": c.Username, | ||
"password": c.Password, | ||
}, nil | ||
} | ||
|
||
func (c *loginCreds) RequireTransportSecurity() bool { | ||
return true | ||
} | ||
|
||
func NewClientTLSFromFile(certFile, serverNameOverride string) (credentials.TransportCredentials, error) { | ||
cp := x509.NewCertPool() | ||
if !cp.AppendCertsFromPEM([]byte(certFile)) { | ||
return nil, fmt.Errorf("credentials: failed to append certificates") | ||
} | ||
return credentials.NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module plumber | ||
|
||
go 1.13 | ||
|
||
require ( | ||
github.com/golang/protobuf v1.4.1 | ||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible | ||
google.golang.org/grpc v1.33.1 | ||
google.golang.org/protobuf v1.25.0 | ||
) |
Oops, something went wrong.