mirror of
https://github.com/ehang-io/nps.git
synced 2025-09-08 00:26:52 +00:00
add new file
This commit is contained in:
71
core/handler/default.go
Normal file
71
core/handler/default.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Handler = (*HttpHandler)(nil)
|
||||
_ Handler = (*HttpsHandler)(nil)
|
||||
_ Handler = (*RdpHandler)(nil)
|
||||
_ Handler = (*RedisHandler)(nil)
|
||||
_ Handler = (*Socks5Handler)(nil)
|
||||
_ Handler = (*TransparentHandler)(nil)
|
||||
_ Handler = (*DefaultHandler)(nil)
|
||||
_ Handler = (*DnsHandler)(nil)
|
||||
_ Handler = (*P2PHandler)(nil)
|
||||
_ Handler = (*QUICHandler)(nil)
|
||||
_ Handler = (*DefaultHandler)(nil)
|
||||
_ Handler = (*Socks5UdpHandler)(nil)
|
||||
)
|
||||
|
||||
type RuleRun interface {
|
||||
RunConn(enet.Conn) (bool, error)
|
||||
RunPacketConn(enet.PacketConn) (bool, error)
|
||||
}
|
||||
|
||||
type DefaultHandler struct {
|
||||
ruleList []RuleRun
|
||||
}
|
||||
|
||||
func NewBaseTcpHandler() *DefaultHandler {
|
||||
return &DefaultHandler{ruleList: make([]RuleRun, 0)}
|
||||
}
|
||||
|
||||
func (b *DefaultHandler) GetName() string {
|
||||
return "default"
|
||||
}
|
||||
|
||||
func (b *DefaultHandler) GetZhName() string {
|
||||
return "默认"
|
||||
}
|
||||
|
||||
func (b *DefaultHandler) HandleConn(_ []byte, c enet.Conn) (bool, error) {
|
||||
return b.processConn(c)
|
||||
}
|
||||
|
||||
func (b *DefaultHandler) AddRule(r RuleRun) {
|
||||
b.ruleList = append(b.ruleList, r)
|
||||
}
|
||||
|
||||
func (b *DefaultHandler) HandlePacketConn(_ enet.PacketConn) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (b *DefaultHandler) processConn(c enet.Conn) (bool, error) {
|
||||
for _, r := range b.ruleList {
|
||||
if ok, err := r.RunConn(c); err != nil || ok {
|
||||
return ok, err
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (b *DefaultHandler) processPacketConn(pc enet.PacketConn) (bool, error) {
|
||||
for _, r := range b.ruleList {
|
||||
if ok, err := r.RunPacketConn(pc); err != nil || ok {
|
||||
return ok, err
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
35
core/handler/dns.go
Normal file
35
core/handler/dns.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
"ehang.io/nps/lib/logger"
|
||||
"github.com/miekg/dns"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type DnsHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (dh *DnsHandler) GetName() string {
|
||||
return "dns"
|
||||
}
|
||||
|
||||
func (dh *DnsHandler) GetZhName() string {
|
||||
return "dns协议"
|
||||
}
|
||||
|
||||
func (dh *DnsHandler) HandlePacketConn(pc enet.PacketConn) (bool, error) {
|
||||
b, _, err := pc.FirstPacket()
|
||||
if err != nil {
|
||||
logger.Warn("firstPacket error", zap.Error(err))
|
||||
return false, nil
|
||||
}
|
||||
m := new(dns.Msg)
|
||||
err = m.Unpack(b)
|
||||
if err != nil {
|
||||
logger.Debug("parse dns request error", zap.Error(err))
|
||||
return false, nil
|
||||
}
|
||||
return dh.processPacketConn(pc)
|
||||
}
|
46
core/handler/dns_test.go
Normal file
46
core/handler/dns_test.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testRule struct {
|
||||
run bool
|
||||
}
|
||||
|
||||
func (t *testRule) RunConn(c enet.Conn) (bool, error) {
|
||||
t.run = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (t *testRule) RunPacketConn(_ enet.PacketConn) (bool, error) {
|
||||
t.run = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func TestHandleDnsPacket(t *testing.T) {
|
||||
lPacketConn, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
h := DnsHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn("www.google.com"), dns.TypeA)
|
||||
m.RecursionDesired = true
|
||||
|
||||
b, err := m.Pack()
|
||||
assert.NoError(t, err)
|
||||
pc := enet.NewReaderPacketConn(nil, b, lPacketConn.LocalAddr())
|
||||
|
||||
assert.NoError(t, pc.SendPacket(b, nil))
|
||||
res, err := h.HandlePacketConn(pc)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
}
|
11
core/handler/handler.go
Normal file
11
core/handler/handler.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package handler
|
||||
|
||||
import "ehang.io/nps/lib/enet"
|
||||
|
||||
type Handler interface {
|
||||
GetName() string
|
||||
GetZhName() string
|
||||
AddRule(RuleRun)
|
||||
HandleConn([]byte, enet.Conn) (bool, error)
|
||||
HandlePacketConn(enet.PacketConn) (bool, error)
|
||||
}
|
30
core/handler/http.go
Normal file
30
core/handler/http.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type HttpHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func NewHttpHandler() *HttpHandler {
|
||||
return &HttpHandler{}
|
||||
}
|
||||
|
||||
func (h *HttpHandler) GetName() string {
|
||||
return "http"
|
||||
}
|
||||
|
||||
func (h *HttpHandler) GetZhName() string {
|
||||
return "http协议"
|
||||
}
|
||||
|
||||
func (h *HttpHandler) HandleConn(b []byte, c enet.Conn) (bool, error) {
|
||||
switch string(b[:3]) {
|
||||
case http.MethodGet[:3], http.MethodHead[:3], http.MethodPost[:3], http.MethodPut[:3], http.MethodPatch[:3], http.MethodDelete[:3], http.MethodConnect[:3], http.MethodOptions[:3], http.MethodTrace[:3]:
|
||||
return h.processConn(c)
|
||||
}
|
||||
return false, nil
|
||||
}
|
27
core/handler/http_test.go
Normal file
27
core/handler/http_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleHttpConn(t *testing.T) {
|
||||
|
||||
h := HttpHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
|
||||
r, err := http.NewRequest("GET", "/", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
b, err := httputil.DumpRequest(r, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
res, err := h.HandleConn(b, nil)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
}
|
33
core/handler/https.go
Normal file
33
core/handler/https.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
)
|
||||
|
||||
const (
|
||||
recordTypeHandshake uint8 = 22
|
||||
typeClientHello uint8 = 1
|
||||
)
|
||||
|
||||
type HttpsHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func NewHttpsHandler() *HttpsHandler {
|
||||
return &HttpsHandler{}
|
||||
}
|
||||
|
||||
func (h *HttpsHandler) GetName() string {
|
||||
return "https"
|
||||
}
|
||||
|
||||
func (h *HttpsHandler) GetZhName() string {
|
||||
return "https协议"
|
||||
}
|
||||
|
||||
func (h *HttpsHandler) HandleConn(b []byte, c enet.Conn) (bool, error) {
|
||||
if b[0] == recordTypeHandshake{
|
||||
return h.processConn(c)
|
||||
}
|
||||
return false, nil
|
||||
}
|
39
core/handler/https_test.go
Normal file
39
core/handler/https_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"ehang.io/nps/lib/enet"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleHttpsConn(t *testing.T) {
|
||||
h := HttpsHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
|
||||
finish := make(chan struct{}, 0)
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
go func() {
|
||||
conn, err := ln.Accept()
|
||||
assert.NoError(t, err)
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
assert.NoError(t, err)
|
||||
res, err := h.HandleConn(buf[:n], enet.NewReaderConn(conn))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
finish <- struct{}{}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
_, err = tls.Dial("tcp", ln.Addr().String(), &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
<-finish
|
||||
}
|
32
core/handler/p2p.go
Normal file
32
core/handler/p2p.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"ehang.io/nps/lib/enet"
|
||||
"ehang.io/nps/lib/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type P2PHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (ph *P2PHandler) GetName() string {
|
||||
return "p2p"
|
||||
}
|
||||
|
||||
func (ph *P2PHandler) GetZhName() string {
|
||||
return "点对点协议"
|
||||
}
|
||||
|
||||
func (ph *P2PHandler) HandlePacketConn(pc enet.PacketConn) (bool, error) {
|
||||
b, _, err := pc.FirstPacket()
|
||||
if err != nil {
|
||||
logger.Warn("firstPacket error", zap.Error(err))
|
||||
return false, nil
|
||||
}
|
||||
if bytes.HasPrefix(b, []byte("p2p")) {
|
||||
return ph.processPacketConn(pc)
|
||||
}
|
||||
return false, nil
|
||||
}
|
26
core/handler/p2p_test.go
Normal file
26
core/handler/p2p_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleP2PPacket(t *testing.T) {
|
||||
|
||||
h := P2PHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8080")
|
||||
assert.NoError(t, err)
|
||||
pc := enet.NewReaderPacketConn(nil, []byte("p2p xxxx"), addr)
|
||||
|
||||
assert.NoError(t, pc.SendPacket([]byte("p2p xxxx"), nil))
|
||||
|
||||
res, err := h.HandlePacketConn(pc)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
}
|
32
core/handler/quic.go
Normal file
32
core/handler/quic.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"ehang.io/nps/lib/enet"
|
||||
"ehang.io/nps/lib/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type QUICHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (qh *QUICHandler) GetName() string {
|
||||
return "quic"
|
||||
}
|
||||
|
||||
func (qh *QUICHandler) GetZhName() string {
|
||||
return "quic协议"
|
||||
}
|
||||
|
||||
func (qh *QUICHandler) HandlePacketConn(pc enet.PacketConn) (bool, error) {
|
||||
b, _, err := pc.FirstPacket()
|
||||
if err != nil {
|
||||
logger.Warn("firstPacket error", zap.Error(err))
|
||||
return false, nil
|
||||
}
|
||||
if len(b) >= 5 && bytes.HasPrefix(b[1:5], []byte{0, 0, 0, 1}) {
|
||||
return qh.processPacketConn(pc)
|
||||
}
|
||||
return false, nil
|
||||
}
|
35
core/handler/quic_test.go
Normal file
35
core/handler/quic_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"ehang.io/nps/lib/enet"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleQUICPacket(t *testing.T) {
|
||||
h := QUICHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
finish := make(chan struct{}, 0)
|
||||
packetConn, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
|
||||
go func() {
|
||||
b := make([]byte, 1500)
|
||||
n, addr, err := packetConn.ReadFrom(b)
|
||||
assert.NoError(t, err)
|
||||
pc := enet.NewReaderPacketConn(nil, b[:n], packetConn.LocalAddr())
|
||||
assert.NoError(t, pc.SendPacket(b[:n], addr))
|
||||
res, err := h.HandlePacketConn(pc)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
finish <- struct{}{}
|
||||
}()
|
||||
go quic.DialAddr(packetConn.LocalAddr().String(), &tls.Config{}, nil)
|
||||
<-finish
|
||||
}
|
24
core/handler/rdp.go
Normal file
24
core/handler/rdp.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
)
|
||||
|
||||
type RdpHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (rh *RdpHandler) GetName() string {
|
||||
return "rdp"
|
||||
}
|
||||
|
||||
func (rh *RdpHandler) GetZhName() string {
|
||||
return "rdp协议"
|
||||
}
|
||||
|
||||
func (rh *RdpHandler) HandleConn(b []byte, c enet.Conn) (bool, error) {
|
||||
if b[0] == 3 && b[1] == 0 {
|
||||
return rh.processConn(c)
|
||||
}
|
||||
return false, nil
|
||||
}
|
37
core/handler/rdp_test.go
Normal file
37
core/handler/rdp_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
"github.com/icodeface/grdp"
|
||||
"github.com/icodeface/grdp/glog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleRdpConn(t *testing.T) {
|
||||
h := RdpHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
|
||||
finish := make(chan struct{}, 0)
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
go func() {
|
||||
conn, err := ln.Accept()
|
||||
assert.NoError(t, err)
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
assert.NoError(t, err)
|
||||
res, err := h.HandleConn(buf[:n], enet.NewReaderConn(conn))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
finish <- struct{}{}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
grdp.NewClient(ln.Addr().String(), glog.DEBUG).Login("Administrator", "123456")
|
||||
}()
|
||||
<-finish
|
||||
}
|
22
core/handler/redis.go
Normal file
22
core/handler/redis.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package handler
|
||||
|
||||
import "ehang.io/nps/lib/enet"
|
||||
|
||||
type RedisHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (rds *RedisHandler) GetName() string {
|
||||
return "redis"
|
||||
}
|
||||
|
||||
func (rds *RedisHandler) GetZhName() string {
|
||||
return "redis协议"
|
||||
}
|
||||
|
||||
func (rds *RedisHandler) HandleConn(b []byte, c enet.Conn) (bool, error) {
|
||||
if b[0] == 42 && b[1] == 49 && b[2] == 13 {
|
||||
return rds.processConn(c)
|
||||
}
|
||||
return false, nil
|
||||
}
|
40
core/handler/redis_test.go
Normal file
40
core/handler/redis_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"ehang.io/nps/lib/enet"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleRedisConn(t *testing.T) {
|
||||
h := RedisHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
|
||||
finish := make(chan struct{}, 0)
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
go func() {
|
||||
conn, err := ln.Accept()
|
||||
assert.NoError(t, err)
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
assert.NoError(t, err)
|
||||
res, err := h.HandleConn(buf[:n], enet.NewReaderConn(conn))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
finish <- struct{}{}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: ln.Addr().String(),
|
||||
})
|
||||
rdb.Ping(context.Background())
|
||||
}()
|
||||
<-finish
|
||||
}
|
22
core/handler/socks5.go
Normal file
22
core/handler/socks5.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package handler
|
||||
|
||||
import "ehang.io/nps/lib/enet"
|
||||
|
||||
type Socks5Handler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (sh *Socks5Handler) GetName() string {
|
||||
return "socks5"
|
||||
}
|
||||
|
||||
func (sh *Socks5Handler) GetZhName() string {
|
||||
return "socks5协议"
|
||||
}
|
||||
|
||||
func (sh *Socks5Handler) HandleConn(b []byte, c enet.Conn) (bool, error) {
|
||||
if b[0] == 5 {
|
||||
return sh.processConn(c)
|
||||
}
|
||||
return false, nil
|
||||
}
|
47
core/handler/socks5_test.go
Normal file
47
core/handler/socks5_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"ehang.io/nps/lib/enet"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleSocks5Conn(t *testing.T) {
|
||||
h := Socks5Handler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
|
||||
finish := make(chan struct{}, 0)
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
go func() {
|
||||
conn, err := ln.Accept()
|
||||
assert.NoError(t, err)
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
assert.NoError(t, err)
|
||||
res, err := h.HandleConn(buf[:n], enet.NewReaderConn(conn))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
finish <- struct{}{}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
transport := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
Proxy: func(_ *http.Request) (*url.URL, error) {
|
||||
return url.Parse(fmt.Sprintf("socks5://%s", ln.Addr().String()))
|
||||
},
|
||||
}
|
||||
|
||||
client := &http.Client{Transport: transport}
|
||||
_, _ = client.Get("https://google.com/")
|
||||
}()
|
||||
<-finish
|
||||
}
|
26
core/handler/socks5_udp.go
Normal file
26
core/handler/socks5_udp.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package handler
|
||||
|
||||
import "ehang.io/nps/lib/enet"
|
||||
|
||||
type Socks5UdpHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (sh *Socks5UdpHandler) GetName() string {
|
||||
return "socks5_udp"
|
||||
}
|
||||
|
||||
func (sh *Socks5UdpHandler) GetZhName() string {
|
||||
return "socks5 udp协议"
|
||||
}
|
||||
|
||||
func (sh *Socks5UdpHandler) HandlePacketConn(pc enet.PacketConn) (bool, error) {
|
||||
b, _, err := pc.FirstPacket()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
if b[0] == 0 {
|
||||
return sh.processPacketConn(pc)
|
||||
}
|
||||
return false, nil
|
||||
}
|
44
core/handler/socks5_udp_test.go
Normal file
44
core/handler/socks5_udp_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/common"
|
||||
"ehang.io/nps/lib/enet"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSocks5Handle(t *testing.T) {
|
||||
h := Socks5UdpHandler{}
|
||||
rule := &testRule{}
|
||||
h.AddRule(rule)
|
||||
|
||||
finish := make(chan struct{}, 0)
|
||||
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
go func() {
|
||||
buf := make([]byte, 1024)
|
||||
n, addr, err := pc.ReadFrom(buf)
|
||||
assert.NoError(t, err)
|
||||
rPc := enet.NewReaderPacketConn(nil, buf[:n], addr)
|
||||
res, err := h.HandlePacketConn(rPc)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, res)
|
||||
assert.Equal(t, true, rule.run)
|
||||
finish <- struct{}{}
|
||||
}()
|
||||
|
||||
data := []byte("test")
|
||||
go func() {
|
||||
cPc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
pAddr, err := common.ParseAddr("8.8.8.8:53")
|
||||
assert.NoError(t, err)
|
||||
b := append([]byte{0, 0, 0}, pAddr...)
|
||||
b = append(b, data...)
|
||||
_, err = cPc.WriteTo(b, pc.LocalAddr())
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
<-finish
|
||||
}
|
21
core/handler/transparent.go
Normal file
21
core/handler/transparent.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ehang.io/nps/lib/enet"
|
||||
)
|
||||
|
||||
type TransparentHandler struct {
|
||||
DefaultHandler
|
||||
}
|
||||
|
||||
func (ts *TransparentHandler) GetName() string {
|
||||
return "transparent"
|
||||
}
|
||||
|
||||
func (ts *TransparentHandler) GetZhName() string {
|
||||
return "linux透明代理协议"
|
||||
}
|
||||
|
||||
func (ts *TransparentHandler) HandleConn(b []byte, c enet.Conn) (bool, error) {
|
||||
return ts.processConn(c)
|
||||
}
|
Reference in New Issue
Block a user