ntcp

package
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2023 License: MIT Imports: 16 Imported by: 0

README

控制连接信令(基于TLS之上,参考socks5协议)

1、协商认证
	+-----+----------+----------+
	| VER | NMETHODS | METHODS  |
	+-----+----------+----------+
	|  1  |    1     | 1 to 255 |
	+-----+----------+----------+

	VER: 指定协议版本号,此处为X'01'
	NMETHODS: 指定客户端支持的认证方法数量
	METHODS: 每个byte对应一个认证方法,目前支持:
	X'00' 不需要身份验证(NO AUTHENTICATION REQUIRED)
	X'01' 用户密码认证(USERNAME/PASSWORD)
	
	服务器需要回应一个数据包
	+-----+--------+
	| VER | METHOD |
	+-----+--------+
	|  1  |   1    |
	+-----+--------+
	VER: 指定协议版本号,此处为X'01'
	METHOD: 指定认证方法。该方法应从客户端提供的认证方法中挑选一个,或者是X'FF'用以拒绝认证。
2、密码认证
	若服务器选择密码认证,则客户端接下来需要发送如下数据包

	+-----+------+----------+------+----------+
	| VER | ULEN |  UNAME   | PLEN |  PASSWD  |
	+-----+------+----------+------+----------+
	|  1  |  1   | 1 to 255 |  1   | 1 to 255 |
	+-----+------+----------+------+----------+
	VER: 指定认证协议版本号,此处为X'01'
	ULEN: 指定后续UNAME的长度
	UNAME: 用户名
	PLEN: 指定后续PASSWD的长度
	PASSWD: 密码
	
	服务器将解析该数据包,并使用其用户名与密码进行验证,然后回复一个数据包
	+-----+--------+
	| VER | STATUS |
	+-----+--------+
	|  1  |   1    |
	+-----+--------+
	VER: 指定认证协议版本号,此处为X'01'
	STATUS: X'00'代表验证成功,可以进行下面的流程。如果该值不是X'00'则代表验证失败,服务器需要关闭此连接。
3、交换支持加密算法
	+-----+----------+-----------------+
	| VER | NMETHODS |  ENCRYP METHOD  |
	+-----+----------+-----------------+
	|  1  |    1     |     1 to 255    |
	+-----+----------+-----------------+	
	VER: 指定协议版本号,此处为X'01'
	NMETHODS: 指定客户端支持的加密方法数量
	ENCRYP METHOD: 每个byte表示一种加密方式。暂时仅支持 chacha20、tea、aes128
	
	服务器将解析该数据包,并与服务器支持的算法匹配,然后回复一个数据包
	+-----+-----+-----------------+-----+------+-------+-------------+-------+-------------+
	| VER | RSV |  ENCRYP METHOD  | RSV | EVER | K1LEN |    KEY1     | K2LEN |     KEY2    |
	+-----+-----+-----------------+-----+------+-------+-------------+-------+-------------+
	|  1  |  1  |        1        |  2  |   1  |   2   |  0 to 65536 |   2   |  0 to 65536 |
	+-----+-----+-----------------+-----+------+-------+-------------+-------+-------------+
	VER: 指定协议版本号,此处为X'01'
	RSV: 保留
	ENCRYP METHOD: 服务器支持的算法。暂时仅支持 chacha20、tea、es128
	RSV: 保留2字节
	EVER: 加密初始版本号
	K1LEN: KEY1长度,网络字节
	KEY1: 秘钥1
	K2LEN: KEY2长度,网络字节
	KEY2: 秘钥2
	
	chacha20,KEY1为key,KEY2为nonce
	tea只使用KEY1。	
	aes128只使用KEY1。
	
4、获得服务端TCP、UDP代理地址
	+-----+-----+
	| VER | CMD |
	+-----+-----+
	|  1  |  1  |
	+-----+-----+
	VER: 指定协议版本号,此处为X'01'
	CMD: 服务器服务地址,X'01'
	
	服务器响应
	+-----+-----------------+-----+--------------+----------+-----+--------------+----------+
	| VER |    UNIQUE ID    |ATYP1| TCP LISTENER |   PORT1  |ATYP2| UDP LISTENER |   PORT2  |
	+-----+-----------------+-----+--------------+----------+-----+--------------+----------+
	|  1  |       4         |  1  |   1 to 255   |    2     |  1  |   1 to 255   |    2     |
	+-----+-----------------+-----+--------------+----------+-----+--------------+----------+
	VER: 指定协议版本号,此处为X'01'
	UNIQUE ID: 客户端唯一标识,网络字节
	ATYP1: 地址类型
		1、IPV4 X'01'
		2、IPV6 X'02'
		3、域名 X'03'
	TCP LISTENER: TCP监听地址
		1、ATYPE=1时,IPV4地址,4个byte(网络字节)
		2、ATYPE=2时,IPV6地址,16个byte
		3、ATYPE=3时,第一个byte指定长度n,其后跟着n个byte标识域名
	PORT1: TCP监听端口
	ATYP2: 地址类型
		1、IPV4 X'01'
		2、IPV6 X'02'
		3、域名 X'03'
	UDP LISTENER: UDP监听地址
		1、ATYPE=1时,IPV4地址,4个byte(网络字节)
		2、ATYPE=2时,IPV6地址,16个byte
		3、ATYPE=3时,第一个byte指定长度n,其后跟着n个byte标识域名
	PORT2: UDP监听端口
	
5、定时更新秘钥
	服务器定时通知客户端更新秘钥(由客户端主动请求有可能被拦截丢弃,导致无法定时更新秘钥,秘钥安全性由TLS保证)
	+-----+-----+-----------------+-----+------+-------+-------------+-------+-------------+
	| VER | CMD |  ENCRYP METHOD  | RSV | EVER | K1LEN |    KEY1     | K2LEN |     KEY2    |
	+-----+-----+-----------------+-----+------+-------+-------------+-------+-------------+
	|  1  |  1  |        1        |  2  |   1  |   2   |  0 to 65536 |   2   |  0 to 65536 |
	+-----+-----+-----------------+-----+------+-------+-------------+-------+-------------+
	VER: 指定协议版本号,此处为X'01'
	CMD: 更新秘钥,X'02'
	ENCRYP METHOD: 服务器支持的算法。暂时仅支持 chacha20、tea、es128,如果为0,则忽略秘钥字段
	RSV: 保留2字节	
	EVER: 最新加密版本号
	K1LEN: KEY1长度,网络字节
	KEY1: 秘钥1
	K2LEN: KEY2长度,网络字节
	KEY2: 秘钥2
	
	chacha20,KEY1为key,KEY2为nonce
	tea只使用KEY1。	
	aes128只使用KEY1。
	
	客户端响应秘钥更新成功
	+-----+-----+------+
	| VER | CMD | EVER |
	+-----+-----+------+
	|  1  |  1  |   1  |
	+-----+-----+------+
	VER: 指定认证协议版本号,此处为X'01'
	CMD: 更新秘钥,X'02'
	EVER: 客户端最新加密版本号
	
6、客户端获取到服务地址后,定时发送心跳
	+-----+-----+
	| VER | CMD |
	+-----+-----+
	|  1  |  1  |
	+-----+-----+
	VER: 指定协议版本号,此处为X'01'
	HEARTBEAT: 心跳码,X'03'
	

代理协议

1、协议头
	a、完整协议头,该协议头出现在TCP第一个数据包和UDP包
	+-----+-----+-----+-----+
	| VER |EVER | CMD | PRO |
	+-----+-----+-----+-----+
	|    RSV    |  CONN ID  |
	+-----------+-----------+
	|        UNIQUE ID      |
	+-----------------------+
	| DATA LEN  |AREA |ATYPE|
	+-----------------------+
	|          HOST         |
	+-----------------------+
	|   PORT    |
	+-----------+
	
	b、该协议头只出现在TCP非第一个数据包
	+-----+-----+-----+-----+
	| VER |EVER | DATA LEN  |
	+-----+-----+-----+-----+
	
	VER: 版本,目前X'01'
	EVER: 秘钥版本号
	CMD: 
		1、CONNECT X'04'
		2、BIND  X'05'		
	PRO: 协议
		1、TCP X'01'
		2、UDP X'02'
		3、ICMP X'08'
		协议详情:
		TCP: 普通tcp代理
		UDP: 普通udp代理
		ICMP: icmp代理(目前没实现)
	RSV: 保留
	CONNECTION ID(CONN ID): 连接唯一标识,在服务器 源地址+ConnectionID(或者UniqueID+ConnectionID) 可以标识服务器唯一连接(ConnectionID不能标识服务器唯一连接),客户端生成(不同的连接必须保证唯一性)。一个客户端最大支持65536个连接。,网络字节
	UNIQUE ID: 用户标识(服务器里面唯一,不是全网唯一值),用于查找用户请求上下文(加密秘钥等)。同一个客户端,所有连接都是一样的。与 CONNECTION ID 不同。,网络字节
	DATA LEN: 数据长度,如果是UDP OVER TCP 必须填写,TCP填0。,网络字节
	AREA: 选区ID,自动路由使用,目前该字段作为后续扩展
	ATYPE: 地址类型(CMD=BIND时,没有该字段)
		1、IPV4 X'01'
		2、IPV6 X'02'
		3、域名 X'03'
	HOST: 目标地址(CMD=BIND时,没有该字段)
		1、ATYPE=1时,IPV4地址,4个byte(网络字节)
		2、ATYPE=2时,IPV6地址,16个byte
		3、ATYPE=3时,第一个byte指定长度n,其后跟着n个byte标识域名
	PORT: 目标端口,网络字节(CMD=BIND时,没有该字段)
	
2、CMD命令
	CONNECT方法:------HOST:PORT标识连接的目标地址,TCP不需要响应客户端。支持TCP/UDP。
	BIND方法:---------客户端:告知服务端需要绑定地址,此时请求的 HOST:PORT 没有意义,填零即可。服务端:告知客户端绑定成功。该模式下可实现nat模式为open状态【TCP暂时不支持】
3、BIND方法
	当CMD=BIND时,DATA的payload为子协议
	+-----+-----+-----+-----+
	| cmd |BindDataLen|ATYPE|
	+-----------------------+
	|          HOST         |
	+-----------------------+
	|   PORT    |
	+-----------+	
	cmd:
		1、BIND X'05'--------请求服务器绑定,由于UDP不可靠,服务端可能会重复收到多个该消息的数据包
		1、BINDSTATUS X'06'--绑定服务状态,如果失败 ATYPE=0,否则 HOST:PORT 表示服务器绑定地址。【TCP暂时不支持】
		2、ACCEPT X'07'------BIND地址接收新请求,TCP有效。【TCP暂时不支持】
		3、RECVFROM X'08'----服务器BIND绑定的TCP或者UDP的地址,接收数据。HOST:PORT 表示来源地址。【TCP暂时不支持】
		4、SENDTO X'09'------客户端通过BIN地址发送数据。HOST:PORT 表示目标地址。【TCP暂时不支持】
		5、PING  X'20'-------探测链路延迟, HOST 为目标地址
		6、MTR  X'21'--------MTR链路检测,每层服务器收到请求都必须响应。HOST:PORT 没有意义,填零即可。响应数据包填写服务端IP,PORT无意义。
	BindDataLen: 数据长度,真实数据长度。网络字节
	ATYPE: 地址类型
		1、IPV4 X'01'
		2、IPV6 X'02'
		3、域名 X'03'
	HOST: 目标地址
		1、ATYPE=1时,IPV4地址,4个byte(网络字节)
		2、ATYPE=2时,IPV6地址,16个byte
		3、ATYPE=3时,第一个byte指定长度n,其后跟着n个byte标识域名
	PORT: 目标端口,网络字节
	
	BIND模式下完整协议如下:
	+-----+-----+-----+-----+
	| VER |EVER | CMD | PRO |
	+-----+-----+-----+-----+
	|    RSV    |  CONN ID  |
	+-----------+-----------+
	|        UNIQUE ID      |
	+-----------------------+
	| DATA LEN  |AREA | cmd |
	+-----------------------+
	|BindDataLen|ATYPE|  HO-|
	+-----------------------+
	|       -ST       |  PO-|
	+-----------------+-----+
	| -RT |
	+-----+
  

Documentation

Overview

NTCP[Network transmission control protocol] Support tcp/udp/tcp bind/udp bind/mgr/ping

Index

Constants

View Source
const (
	NoAuth          = uint8(0)
	UserPassAuth    = uint8(1)
	UserAuthVersion = uint8(1)
	AuthSuccess     = uint8(0)
	AuthFailure     = uint8(1)
	NoAcceptable    = uint8(255)
)
View Source
const (
	FATAL = "fatal"
	ERROR = "error"
	WARN  = "warn"
	INFO  = "info"
	DEBUG = "debug"
)
View Source
const (
	NtcpVersion   = uint8(0x01)
	NtcpHeaderLen = 16
	// 命令
	ServerAddrCmd = uint8(0x01) //获取服务端绑定地址
	CryptoCmd     = uint8(0x02) //密钥交换
	HeartBeatCmd  = uint8(0x03) //心跳
	ConnectCmd    = uint8(0x04) //发起代理连接
	BindCmd       = uint8(0x05) //发起代理绑定
	BindStatusCmd = uint8(0x06) //Bind响应
	AcceptCmd     = uint8(0x07) //代理接受TCP请求
	RecvFromCmd   = uint8(0x08) //bind代理接收UDP数据
	SendToCmd     = uint8(0x09) //bind代理发送UDP数据
	PingCmd       = uint8(0x20) //ping
	MtrCmd        = uint8(0x21) //mtr
	// 协议
	ProTcp  = uint8(0x01) // tcp
	ProUdp  = uint8(0x02) // udp
	ProIcmp = uint8(0x03) // icmp

	NtcpHeaderSize = 16
)
View Source
const (
	TimeoutSecond    = time.Second * 30
	UpdateCryptoTime = time.Minute * 5
)
View Source
const (
	UdpListenerReadBufferSize  = 64 * 1024
	UdpListenerWriteBufferSize = 64 * 1024
	UdpReadBufferSize          = 32 * 1024
	UdpWriteBufferSize         = 32 * 1024
	TcpReadBufferSize          = 32 * 1024
	TcpWriteBufferSize         = 32 * 1024

	PacketBufSize   = 1024 * 16
	MemPoolNodeSize = 1600
)
View Source
const (
	TdpHeaderLen = 12

	TdpVersion = 0
)
View Source
const (
	NotUseAddr = "127.0.0.1:1"
)

Variables

View Source
var (
	UserAuthFailed  = fmt.Errorf("User Authentication Failed")
	NoSupportedAuth = fmt.Errorf("No Supported Authentication")
)
View Source
var (
	MaxConnCount = uint32(102400) // NTCP并发连接数

	BitValue01 = byte(0x01)
)

Functions

func Addr2Byte

func Addr2Byte(addrSpec *AddrSpec) (uint8, []byte, error)

func GetATyp

func GetATyp(aTyp uint8) string

func GetCmd

func GetCmd(cmd uint8) string

func GetProtocol

func GetProtocol(pro uint8) string

func LegalProxyMode

func LegalProxyMode(cmd uint8) bool

Types

type AES128Context

type AES128Context struct {
	// 加密方法
	Method crypto.CryptoType
	// 加密秘钥版本 秘钥会定时更新 表示当前 Keys 索引
	Version uint8
	// Keys 数组长度由 version最大值决定
	Keys [keyArrayLen][]byte
	// contains filtered or unexported fields
}

AES128

func NewAES128Context

func NewAES128Context(cryptoCode crypto.CryptoType) *AES128Context

func (*AES128Context) GenerateKey

func (aes128 *AES128Context) GenerateKey()

func (*AES128Context) GetCode

func (aes128 *AES128Context) GetCode() crypto.CryptoType

func (*AES128Context) GetKey

func (aes128 *AES128Context) GetKey(version uint8) ([][]byte, bool)

func (*AES128Context) GetVersion

func (aes128 *AES128Context) GetVersion() uint8

func (*AES128Context) SetKey

func (aes128 *AES128Context) SetKey(version uint8, key [][]byte) bool

type AddrSpec

type AddrSpec struct {
	FQDN string
	IP   net.IP
	Port int
}

AddrSpec 用于记录地址 可能是 IPv4, IPv6, 域名

func Addr2AddrSpec

func Addr2AddrSpec(addr string) (*AddrSpec, error)

func (AddrSpec) Address

func (a AddrSpec) Address() string

func (*AddrSpec) String

func (a *AddrSpec) String() string

type AuthContext

type AuthContext struct {
	// 身份验证方法
	Method uint8
	//协商期间提供的有效载荷。
	//Key取决于使用的身份验证方法。
	//对于用户密码认证方式包含用户名
	Payload map[string]string
}

type Authenticator

type Authenticator interface {
	Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)
	GetCode() uint8
}

type BindConn

type BindConn interface {
	Read(b []byte) (n int, err error)
	Write(b []byte) (n int, err error)
	Close() error
	LocalAddr() net.Addr
	RemoteAddr() net.Addr
	SetDeadline(t time.Time) error
	SetReadDeadline(t time.Time) error
	SetWriteDeadline(t time.Time) error
	// 获取代理服务bind地址
	ProxyBindAddr() (string, error)
	// 读取数据
	ReadFrom(b []byte) (int, net.Addr, error)
	// 发送数据
	WriteTo(b []byte, addr net.Addr) (int, error)
}

type BindDatagram

type BindDatagram struct {

	// 实际要传输的数据
	Data []byte
	// contains filtered or unexported fields
}

func NewBindDatagram

func NewBindDatagram(ctx context.Context,
	cmd, aTyp byte,
	host, port, data []byte) *BindDatagram

请看协议头说明

func NewBindDatagramFromByte

func NewBindDatagramFromByte(ctx context.Context, bs []byte) (*BindDatagram, error)

请看协议头说明 * @param bs 切片会被引用,请注意使用

func NewBindDatagramFromIO

func NewBindDatagramFromIO(ctx context.Context, bufIO io.Reader) (*BindDatagram, error)

请看协议头说明 tcp才会调用

func (*BindDatagram) Address

func (d *BindDatagram) Address() string

func (*BindDatagram) Cmd

func (d *BindDatagram) Cmd() byte

func (*BindDatagram) Host

func (d *BindDatagram) Host() string

func (*BindDatagram) Port

func (d *BindDatagram) Port() int

type ChaCha20Context

type ChaCha20Context struct {
	// 加密方法
	Method crypto.CryptoType
	// 加密秘钥版本 秘钥会定时更新 表示当前 Keys 索引
	Version uint8
	// Keys 数组长度由 version最大值决定
	Keys [keyArrayLen]*ChaCha20Key
	// contains filtered or unexported fields
}

func NewChaCha20Context

func NewChaCha20Context(cryptoCode crypto.CryptoType) *ChaCha20Context

func (*ChaCha20Context) GenerateKey

func (chacha *ChaCha20Context) GenerateKey()

func (*ChaCha20Context) GetCode

func (chacha *ChaCha20Context) GetCode() crypto.CryptoType

func (*ChaCha20Context) GetKey

func (chacha *ChaCha20Context) GetKey(version uint8) ([][]byte, bool)

func (*ChaCha20Context) GetVersion

func (chacha *ChaCha20Context) GetVersion() uint8

func (*ChaCha20Context) SetKey

func (chacha *ChaCha20Context) SetKey(version uint8, key [][]byte) bool

type ChaCha20Key

type ChaCha20Key struct {
	Key   []byte
	Nonce []byte
}

chacha20

type CredentialStore

type CredentialStore interface {
	Valid(user, password string) bool
	Get() (string, string, bool)
}

CredentialStore 用于支持用户密码认证

type CryptoStore

type CryptoStore interface {
	SetMethod(method crypto.CryptoType)
	Valid(method crypto.CryptoType) bool
	GetMethods() []crypto.CryptoType
}

设置支持加密算法

type CryptoSupport

type CryptoSupport map[crypto.CryptoType]struct{}

func (CryptoSupport) GetMethods

func (c CryptoSupport) GetMethods() []crypto.CryptoType

func (CryptoSupport) SetMethod

func (c CryptoSupport) SetMethod(method crypto.CryptoType)

func (CryptoSupport) Valid

func (c CryptoSupport) Valid(method crypto.CryptoType) bool

type CryptorContext

type CryptorContext interface {
	// 生成秘钥
	GenerateKey()
	// 获取对应版本的秘钥
	GetKey(version uint8) ([][]byte, bool)
	// 获取算法code
	GetCode() crypto.CryptoType
	// 获取秘钥版本
	GetVersion() uint8
	// 客户端使用
	SetKey(version uint8, key [][]byte) bool
}

func GetCryptoContext

func GetCryptoContext(cryptoCode crypto.CryptoType) CryptorContext

type Datagram

type Datagram struct {

	// 实际要传输的数据
	Data []byte
	// contains filtered or unexported fields
}

func NewDatagram

func NewDatagram(ctx context.Context,
	cryptoVer, cmd, protocol, aTyp, area byte,
	connId uint16,
	uid uint32,
	host, port, data []byte) *Datagram

请看协议头说明

func NewDatagramFromByte

func NewDatagramFromByte(ctx context.Context, bs []byte) (*Datagram, error)

请看协议头说明 * @param bs 切片会被引用,请注意使用

func ReadDatagramHeaderFromIO

func ReadDatagramHeaderFromIO(ctx context.Context, bufIO io.Reader) (*Datagram, error)

请看协议头说明 tcp才会调用

func (*Datagram) Address

func (d *Datagram) Address() string

func (*Datagram) Area

func (d *Datagram) Area() byte

func (*Datagram) Cmd

func (d *Datagram) Cmd() byte

func (*Datagram) ConnectionId

func (d *Datagram) ConnectionId() uint16

func (*Datagram) Host

func (d *Datagram) Host() string

func (*Datagram) Port

func (d *Datagram) Port() int

func (*Datagram) Protocol

func (d *Datagram) Protocol() byte

func (*Datagram) Uid

func (d *Datagram) Uid() uint32

type DatagramS

type DatagramS struct {

	// 实际要传输的数据
	Data []byte
	// contains filtered or unexported fields
}

func NewDatagramS

func NewDatagramS(ctx context.Context,
	cryptoVer byte,
	data []byte) *DatagramS

请看协议头说明

func NewDatagramSFromByte

func NewDatagramSFromByte(ctx context.Context, bs []byte) (*DatagramS, error)

请看协议头说明 * @param bs 切片会被引用,请注意使用

func NewDatagramSFromIO

func NewDatagramSFromIO(ctx context.Context, bufIO io.Reader) (*DatagramS, error)

请看协议头说明

type Logger

type Logger interface {
	PrintLog(level string, format string, v ...any)
}

type Mem

type Mem struct{}

func CreateMemMgr

func CreateMemMgr() *Mem

func (*Mem) Alloc

func (m *Mem) Alloc(ctx context.Context, size int) []byte

func (*Mem) Free

func (m *Mem) Free(ctx context.Context, bs []byte)

type MemAllocation

type MemAllocation interface {
	Alloc(ctx context.Context, size int) []byte
	Free(ctx context.Context, bs []byte)
}

mem allocation by ctinkong

type MemMgr

type MemMgr interface {
	Create(ctx context.Context) MemAllocation
}

mem mgr by ctinkong

type NoAuthenticator

type NoAuthenticator struct{}

无认证

func (NoAuthenticator) Authenticate

func (a NoAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)

func (NoAuthenticator) GetCode

func (a NoAuthenticator) GetCode() uint8

type NoneContext

type NoneContext struct {
	// 加密方法
	Method crypto.CryptoType
	// 加密秘钥版本 秘钥会定时更新 表示当前 Keys 索引
	Version uint8
	// Keys 数组长度由 version最大值决定
	Keys [keyArrayLen][]byte
	// contains filtered or unexported fields
}

None

func NewNoneContext

func NewNoneContext(cryptoCode crypto.CryptoType) *NoneContext

func (*NoneContext) GenerateKey

func (none *NoneContext) GenerateKey()

func (*NoneContext) GetCode

func (none *NoneContext) GetCode() crypto.CryptoType

func (*NoneContext) GetKey

func (none *NoneContext) GetKey(version uint8) ([][]byte, bool)

func (*NoneContext) GetVersion

func (none *NoneContext) GetVersion() uint8

func (*NoneContext) SetKey

func (none *NoneContext) SetKey(version uint8, key [][]byte) bool

type NtcpDial

type NtcpDial func(ctx context.Context, network, addr string) (net.Conn, error)

发起连接

type NtcpListen

type NtcpListen func(network, address string) (net.Listener, error)

监听地址

type NtcpLogger

type NtcpLogger struct {
}

func (*NtcpLogger) PrintLog

func (nl *NtcpLogger) PrintLog(level string, format string, v ...any)

type NtcpNewConn

type NtcpNewConn func(session Session, proxyHeader ProxyHeader) (net.Conn, error)

新连接来了

type NtcpNewPeer

type NtcpNewPeer func(src, dst net.Conn) error

新的代理连接 并负责释放 src与dst

type NtcpSession

type NtcpSession struct {
	// contains filtered or unexported fields
}

func NewSession

func NewSession(conf *SessionConfig, cb NtcpSessionDead) *NtcpSession

*NewSession 创建会话,客户端使用 *@param conf 会话配置

func (*NtcpSession) Bind

func (ns *NtcpSession) Bind(network string, area uint8) (BindConn, error)

* Bind 发起bind代理连接 * @param network 网络类型,目前支持udp * @param area 选区 如果没有填 0 即可

func (*NtcpSession) Close

func (ns *NtcpSession) Close() error

func (*NtcpSession) Connect

func (ns *NtcpSession) Connect(network, dstAddr string, area uint8) (net.Conn, error)

* Connect 发起connect代理连接 * @param network 网络类型,目前支持tcp、udp * @param dstAddr 目标地址,支持ip:port、domain:port * @param area 选区 如果没有填 0 即可

func (*NtcpSession) ConnectWithBind

func (ns *NtcpSession) ConnectWithBind(network, dstAddr string, area uint8) (net.Conn, error)

* ConnectWithBind 发起代理连接,中间节点调用 * @param network 网络类型,目前支持tcp、udp * @param dstAddr 目标地址,支持ip:port、domain:port * @param area 选区 如果没有填 0 即可

func (*NtcpSession) CryptoSyncVersion

func (ns *NtcpSession) CryptoSyncVersion() uint8

服务端与客户端同步的加密版本号

func (*NtcpSession) Cryptoer

func (ns *NtcpSession) Cryptoer() CryptorContext

定义接口

func (*NtcpSession) Dial

func (ns *NtcpSession) Dial(ctx context.Context, addr string) error

Dial 发起ntcp连接,整个过程包括协商认证、接收初始化秘钥、获取服务器代理地址,然后启动协程

func (*NtcpSession) GetBindHost

func (ns *NtcpSession) GetBindHost() string

定义接口

func (*NtcpSession) IsDead

func (ns *NtcpSession) IsDead() bool

定义接口

func (*NtcpSession) Logger

func (ns *NtcpSession) Logger() Logger

定义接口

func (*NtcpSession) SessionUid

func (ns *NtcpSession) SessionUid() uint32

定义接口

type NtcpSessionDead

type NtcpSessionDead func(session *NtcpSession)

NtcpSession 异常断开回调

type NtcpTcp

type NtcpTcp struct {
	// contains filtered or unexported fields
}

func NewNtcpTcp

func NewNtcpTcp(session Session, area uint8) *NtcpTcp

客户端使用

* NewNtcpTcpWithConn 创建tcp * @param session 会话 * @param area 选区ID

func NewNtcpTcpWithConn

func NewNtcpTcpWithConn(session Session, conn net.Conn) *NtcpTcp

服务端使用

* NewNtcpTcpWithConn 创建tcp * @param session 会话 * @param conn tcp连接

func (*NtcpTcp) Close

func (nc *NtcpTcp) Close() error

func (*NtcpTcp) Dial

func (nc *NtcpTcp) Dial(ctx context.Context,
	proxyAddr *AddrSpec,
	dstAddr *AddrSpec,
	ntcpDial NtcpDial) error

客户端使用

* Dial 发起代理连接 * @param proxyAddr 代理服务器地址 * @param dstAddr 目标地址 * @param ntcpDial dial回调函数

func (*NtcpTcp) LocalAddr

func (nc *NtcpTcp) LocalAddr() net.Addr

func (*NtcpTcp) Read

func (nc *NtcpTcp) Read(b []byte) (n int, err error)

func (*NtcpTcp) RemoteAddr

func (nc *NtcpTcp) RemoteAddr() net.Addr

func (*NtcpTcp) SetDeadline

func (nc *NtcpTcp) SetDeadline(t time.Time) error

func (*NtcpTcp) SetReadDeadline

func (nc *NtcpTcp) SetReadDeadline(t time.Time) error

func (*NtcpTcp) SetWriteDeadline

func (nc *NtcpTcp) SetWriteDeadline(t time.Time) error

func (*NtcpTcp) Write

func (nc *NtcpTcp) Write(b []byte) (n int, err error)

type NtcpTdp

type NtcpTdp struct {
	// contains filtered or unexported fields
}

func NewNtcpTdp

func NewNtcpTdp(session Session) *NtcpTdp

客户端使用

* NewNtcpTdpWithConn 创建tcp

func NewNtcpTdpWithConn

func NewNtcpTdpWithConn(session Session, conn net.Conn) *NtcpTdp

服务端使用

* NewNtcpTdpWithConn 创建tcp * @param conn tcp连接

func (*NtcpTdp) Close

func (nc *NtcpTdp) Close() error

func (*NtcpTdp) Dial

func (nc *NtcpTdp) Dial(ctx context.Context,
	proxyAddr *AddrSpec,
	ntcpDial NtcpDial) error

客户端使用

* Dial 发起代理连接 * @param proxyAddr 代理服务器地址 * @param dstAddr 目标地址 * @param ntcpDial dial回调函数

func (*NtcpTdp) LocalAddr

func (nc *NtcpTdp) LocalAddr() net.Addr

func (*NtcpTdp) Read

func (nc *NtcpTdp) Read(b []byte) (n int, err error)

func (*NtcpTdp) RemoteAddr

func (nc *NtcpTdp) RemoteAddr() net.Addr

func (*NtcpTdp) SetDeadline

func (nc *NtcpTdp) SetDeadline(t time.Time) error

func (*NtcpTdp) SetReadDeadline

func (nc *NtcpTdp) SetReadDeadline(t time.Time) error

func (*NtcpTdp) SetWriteDeadline

func (nc *NtcpTdp) SetWriteDeadline(t time.Time) error

func (*NtcpTdp) Write

func (nc *NtcpTdp) Write(b []byte) (n int, err error)

type NtcpUdp

type NtcpUdp struct {
	// contains filtered or unexported fields
}

func NewNtcpUdp

func NewNtcpUdp(session Session,
	dstAddr *AddrSpec,
	area uint8) *NtcpUdp

* NewNtcpUdp 客户端创建udp * @param session 会话 * @param area 选区ID

func NewNtcpUdpOverTdp

func NewNtcpUdpOverTdp(session Session,
	mem MemAllocation,
	dstAddr *AddrSpec,
	area uint8) (*NtcpUdp, error)

* NewNtcpUdpWithTdpConn 客户端新的connect请求,基于tdp基础上,只会在客户端使用 * @param session 会话 * @param mem 内存器 * @param area 选取ID

func NewNtcpUdpOverTdpWithBind

func NewNtcpUdpOverTdpWithBind(session Session,
	tdpConn *NtcpTdp,
	mem MemAllocation,
	area uint8) (*NtcpUdp, error)

* NewNtcpUdpWithTdpConn 第一跳通过tdp接收到的BindCmd请求 * @param session 会话 * @param tdpConn tdp连接 * @param mem 内存管理器 * @param area 选取ID

func NewNtcpUdpWithBind

func NewNtcpUdpWithBind(session Session,
	dstAddr *AddrSpec,
	area uint8) *NtcpUdp

* NewNtcpUdpWithBind 中间代理bind客户端使用,注意是代理服务器上的客户端角色 * @param session 会话 * @param area 选区ID

func NewNtcpUdpWithConn

func NewNtcpUdpWithConn(session Session,
	closeCB closeOneFn,
	conn *net.UDPConn,
	from *net.UDPAddr,
	mem MemAllocation,
	cmd uint8,
	connId uint16,
	area uint8) *NtcpUdp

* NewNtcpUdpWithConn 服务端收到新请求,创建udp * @param session 会话 * @param conn 服务端监听连接 * @param from 连接来源 * @param cmd cmd,可能是 connect/bind * @param connId 连接ID * @param area 选取ID

func NewNtcpUdpWithTdpConn

func NewNtcpUdpWithTdpConn(session Session,
	tdpConn *NtcpTdp,
	mem MemAllocation,
	dstAddr *AddrSpec,
	area uint8) (*NtcpUdp, error)

* NewNtcpUdpWithTdpConn 服务端收到客户端新的connect请求,基于tdp基础上,只会在上车节点使用 * @param session 会话 * @param connId 连接ID * @param area 选取ID

func (*NtcpUdp) Close

func (nc *NtcpUdp) Close() error

func (*NtcpUdp) Dial

func (nc *NtcpUdp) Dial(ctx context.Context,
	proxyAddr *AddrSpec,
	ntcpDial NtcpDial) error

客户端使用

func (*NtcpUdp) DialTdp

func (nc *NtcpUdp) DialTdp(ctx context.Context,
	proxyAddr *AddrSpec) error

客户端使用

func (*NtcpUdp) LocalAddr

func (nc *NtcpUdp) LocalAddr() net.Addr

func (*NtcpUdp) Read

func (nc *NtcpUdp) Read(b []byte) (n int, err error)

func (*NtcpUdp) RemoteAddr

func (nc *NtcpUdp) RemoteAddr() net.Addr

func (*NtcpUdp) SetDeadline

func (nc *NtcpUdp) SetDeadline(t time.Time) error

func (*NtcpUdp) SetReadDeadline

func (nc *NtcpUdp) SetReadDeadline(t time.Time) error

func (*NtcpUdp) SetWriteDeadline

func (nc *NtcpUdp) SetWriteDeadline(t time.Time) error

func (*NtcpUdp) Write

func (nc *NtcpUdp) Write(b []byte) (n int, err error)

type NtcpUdpBind

type NtcpUdpBind struct {
	// contains filtered or unexported fields
}

* NtcpUdpBind bing模式的普通udp,只有在代理的链路的客户端与下车节点使用,而且仅作为dst连接 ,中间节点传输依然使用 NtcpUdp

func NewNtcpUdpBind

func NewNtcpUdpBind(session Session, area uint8) *NtcpUdpBind

* NewNtcpUdpBind 客户端创建udp * @param session 会话 * @param area 选区ID

func NewNtcpUdpBindOverTdp

func NewNtcpUdpBindOverTdp(session Session,
	mem MemAllocation,
	area uint8) (*NtcpUdpBind, error)

* NewNtcpUdpBindOverTdp 服务端收到客户端新的bind请求,基于tdp基础上,只会在中间节点使用 * @param session 会话 * @param connId 连接ID * @param area 选取ID

func NewNtcpUdpBindWithConn

func NewNtcpUdpBindWithConn(session Session,
	mem MemAllocation,
	connId uint16,
	area uint8) (*NtcpUdpBind, error)

* NewNtcpUdpBindWithConn 服务端收到客户端新的bind请求,创建udp * @param session 会话 * @param connId 连接ID * @param area 选取ID

func (*NtcpUdpBind) Close

func (nc *NtcpUdpBind) Close() error

func (*NtcpUdpBind) Dial

func (nc *NtcpUdpBind) Dial(ctx context.Context,
	proxyAddr *AddrSpec,
	ntcpDial NtcpDial) error

客户端使用

func (*NtcpUdpBind) DialTdp

func (nc *NtcpUdpBind) DialTdp(ctx context.Context,
	proxyAddr *AddrSpec) error

客户端使用

func (*NtcpUdpBind) LocalAddr

func (nc *NtcpUdpBind) LocalAddr() net.Addr

func (*NtcpUdpBind) ProxyBindAddr

func (nc *NtcpUdpBind) ProxyBindAddr() (string, error)

客户端使用 获取代理服务bind地址

func (*NtcpUdpBind) Read

func (nc *NtcpUdpBind) Read(b []byte) (n int, err error)

服务端下车节点使用,中间节点传输依然使用 NtcpUdp

func (*NtcpUdpBind) ReadFrom

func (nc *NtcpUdpBind) ReadFrom(b []byte) (int, net.Addr, error)

客户端调用

func (*NtcpUdpBind) RemoteAddr

func (nc *NtcpUdpBind) RemoteAddr() net.Addr

func (*NtcpUdpBind) SetDeadline

func (nc *NtcpUdpBind) SetDeadline(t time.Time) error

func (*NtcpUdpBind) SetReadDeadline

func (nc *NtcpUdpBind) SetReadDeadline(t time.Time) error

func (*NtcpUdpBind) SetWriteDeadline

func (nc *NtcpUdpBind) SetWriteDeadline(t time.Time) error

func (*NtcpUdpBind) Write

func (nc *NtcpUdpBind) Write(b []byte) (n int, err error)

服务端下车节点使用,数据不需要解密,中间节点传输依然使用 NtcpUdp

func (*NtcpUdpBind) WriteTo

func (nc *NtcpUdpBind) WriteTo(b []byte, addr net.Addr) (int, error)

客户端调用

type ProxyHeader

type ProxyHeader interface {
	// 获取代理目标地址
	Address() string
	// 获取协议
	Protocol() byte
	// 获取代理命令
	Cmd() byte
	// 获取会话ID
	Uid() uint32
	// 获取连接ID
	ConnectionId() uint16
	// 获取选区ID
	Area() byte
}

type ProxyServer

type ProxyServer struct {
	// contains filtered or unexported fields
}

func (*ProxyServer) Close

func (p *ProxyServer) Close() error

type ProxyUdp

type ProxyUdp struct {
	// contains filtered or unexported fields
}

type Request

type Request struct {
	Config              *ServerConfig
	AuthContext         *AuthContext
	Version             uint8          // 协议版本
	ClientCryptoVersion uint8          // 客户端加密版本
	Uid                 uint32         // 连接唯一标识
	CryptorContext      CryptorContext // 秘钥上下文
	Conn                net.Conn       // io
	Log                 Logger         // 日志
	// contains filtered or unexported fields
}

请求

func NewRequest

func NewRequest(s *Server, conn net.Conn) (*Request, error)

创建连接请求

func (*Request) CryptoSyncVersion

func (r *Request) CryptoSyncVersion() uint8

服务端与客户端同步的加密版本号

func (*Request) Cryptoer

func (r *Request) Cryptoer() CryptorContext

定义接口

func (*Request) GetBindHost

func (r *Request) GetBindHost() string

定义接口

func (*Request) IsDead

func (r *Request) IsDead() bool

定义接口

func (*Request) Logger

func (r *Request) Logger() Logger

定义接口

func (*Request) SessionUid

func (r *Request) SessionUid() uint32

定义接口

func (*Request) UpdateSyncVersion

func (r *Request) UpdateSyncVersion(v uint8)

type Server

type Server struct {
	// contains filtered or unexported fields
}

ntcp 服务

func NewServer

func NewServer(conf *ServerConfig, ntcpNewConn NtcpNewConn, ntcpNewPeer NtcpNewPeer) (*Server, error)

创建 ntcp 服务

*NewServer 创建ntcp服务 *@param conf 服务配置 *@param ntcpNewConn 收到新的代理请求,回调创建连接 *@param ntcpNewPeer 新的代理匹配成功了 该回调函数处理代理数据转发逻辑,回调函数不需要Close连接

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(addr string, tcpProxyAddr, udpProxyAddr, tdpProxyAddr string) error

开始服务

type ServerConfig

type ServerConfig struct {
	// 使用者可提供自定义认证方式
	// 如果 AuthMethods 不为空 则会忽略 Credentials
	AuthMethods []Authenticator
	// AuthMethods 为空:如果 Credentials 不为空,则支持用户密码认证,否则不需要认证
	// AuthMethods 不为空: 忽略 Credentials
	Credentials CredentialStore
	// 自定义存放支持加密算法
	CryptoStores CryptoStore
	// BindHost 用于TCP/UDP代理绑定host(域名或者IP),可被客户端连接
	BindHost string
	// 新连接
	Dial NtcpDial
	// 新绑定请求,客户端使用bind命令是需要调用上层业务
	Disten NtcpListen
	// 日志
	Log Logger
	// 内存分配器
	MemMgr MemMgr
}

服务器配置

func (*ServerConfig) GetBindHost

func (s *ServerConfig) GetBindHost() string

type Session

type Session interface {
	// 加解密器
	Cryptoer() CryptorContext
	// 服务端与客户端同步的加密版本号
	CryptoSyncVersion() uint8
	// 获取uid
	SessionUid() uint32
	// 日志接口
	Logger() Logger
	//
	GetBindHost() string
	// session是否结束了
	IsDead() bool
}

type SessionConfig

type SessionConfig struct {
	Credentials  CredentialStore   // 保存用户密码
	CryptoMethod crypto.CryptoType // 加密方式
	Log          Logger            // 日志
	Dial         NtcpDial          // 可自定义连接函数
}

客户端配置

type StaticCredentials

type StaticCredentials map[string]string

StaticCredentials 声明map类型

func (StaticCredentials) Get

func (s StaticCredentials) Get() (string, string, bool)

func (StaticCredentials) Valid

func (s StaticCredentials) Valid(user, password string) bool

type TdpData

type TdpData struct {

	// 实际要传输的数据
	Data []byte
	// contains filtered or unexported fields
}

type TeaContext

type TeaContext struct {
	// 加密方法
	Method crypto.CryptoType
	// 加密秘钥版本 秘钥会定时更新 表示当前 Keys 索引
	Version uint8
	// Keys 数组长度由 version最大值决定
	Keys [keyArrayLen]*TeaKey
	// contains filtered or unexported fields
}

func NewTeaContext

func NewTeaContext(cryptoCode crypto.CryptoType) *TeaContext

func (*TeaContext) GenerateKey

func (tea *TeaContext) GenerateKey()

func (*TeaContext) GetCode

func (tea *TeaContext) GetCode() crypto.CryptoType

func (*TeaContext) GetKey

func (tea *TeaContext) GetKey(version uint8) ([][]byte, bool)

func (*TeaContext) GetVersion

func (tea *TeaContext) GetVersion() uint8

func (*TeaContext) SetKey

func (tea *TeaContext) SetKey(version uint8, key [][]byte) bool

type TeaKey

type TeaKey struct {
	Key     []byte
	ByteKey []byte
}

tea chacha20

type UserPassAuthenticator

type UserPassAuthenticator struct {
	Credentials CredentialStore
}

用户名密码认证

func (UserPassAuthenticator) Authenticate

func (a UserPassAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)

func (UserPassAuthenticator) GetCode

func (a UserPassAuthenticator) GetCode() uint8

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL