chore: listeners support shadowsocks/vmess
This commit is contained in:
parent
2e22c712af
commit
b7d976796a
24 changed files with 453 additions and 125 deletions
|
@ -4,12 +4,20 @@ import (
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Addition struct {
|
type Addition func(metadata *C.Metadata)
|
||||||
InName string
|
|
||||||
SpecialRules string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a Addition) Apply(metadata *C.Metadata) {
|
func (a Addition) Apply(metadata *C.Metadata) {
|
||||||
metadata.InName = a.InName
|
a(metadata)
|
||||||
metadata.SpecialRules = a.SpecialRules
|
}
|
||||||
|
|
||||||
|
func WithInName(name string) Addition {
|
||||||
|
return func(metadata *C.Metadata) {
|
||||||
|
metadata.InName = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithSpecialRules(specialRules string) Addition {
|
||||||
|
return func(metadata *C.Metadata) {
|
||||||
|
metadata.SpecialRules = specialRules
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,10 @@ type Listener interface {
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type AdvanceListener interface {
|
type MultiAddrListener interface {
|
||||||
Close() error
|
Close() error
|
||||||
Config() string
|
Config() string
|
||||||
AddrList() (addrList []net.Addr)
|
AddrList() (addrList []net.Addr)
|
||||||
HandleConn(conn net.Conn, in chan<- ConnContext)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type InboundListener interface {
|
type InboundListener interface {
|
||||||
|
|
|
@ -121,7 +121,7 @@ tunnels:
|
||||||
- tcp/udp,127.0.0.1:6553,114.114.114.114:53,proxy
|
- tcp/udp,127.0.0.1:6553,114.114.114.114:53,proxy
|
||||||
- tcp,127.0.0.1:6666,rds.mysql.com:3306,vpn
|
- tcp,127.0.0.1:6666,rds.mysql.com:3306,vpn
|
||||||
# full yaml config
|
# full yaml config
|
||||||
- network: [tcp, udp]
|
- network: [ tcp, udp ]
|
||||||
address: 127.0.0.1:7777
|
address: 127.0.0.1:7777
|
||||||
target: target.com
|
target: target.com
|
||||||
proxy: proxy
|
proxy: proxy
|
||||||
|
@ -693,13 +693,32 @@ listeners:
|
||||||
type: tproxy
|
type: tproxy
|
||||||
port: 10812
|
port: 10812
|
||||||
listen: 0.0.0.0
|
listen: 0.0.0.0
|
||||||
# udp: false # 默认 true
|
|
||||||
# rule: sub-rule
|
# rule: sub-rule
|
||||||
|
# udp: false # 默认 true
|
||||||
|
|
||||||
|
- name: shadowsocks-in-1
|
||||||
|
type: shadowsocks
|
||||||
|
port: 10813
|
||||||
|
listen: 0.0.0.0
|
||||||
|
# rule: sub-rule
|
||||||
|
password: vlmpIPSyHH6f4S8WVPdRIHIlzmB+GIRfoH3aNJ/t9Gg=
|
||||||
|
cipher: 2022-blake3-aes-256-gcm
|
||||||
|
|
||||||
|
- name: vmess-in-1
|
||||||
|
type: vmess
|
||||||
|
port: 10814
|
||||||
|
listen: 0.0.0.0
|
||||||
|
# rule: sub-rule
|
||||||
|
users:
|
||||||
|
- username: 1
|
||||||
|
uuid: 9d0cb9d0-964f-4ef6-897d-6c6b3ccf9e68
|
||||||
|
alterId: 1
|
||||||
|
|
||||||
- name: tuic-in-1
|
- name: tuic-in-1
|
||||||
type: tuic
|
type: tuic
|
||||||
port: 10813
|
port: 10815
|
||||||
listen: 0.0.0.0
|
listen: 0.0.0.0
|
||||||
|
# rule: sub-rule
|
||||||
# token:
|
# token:
|
||||||
# - TOKEN
|
# - TOKEN
|
||||||
# certificate: ./server.crt
|
# certificate: ./server.crt
|
||||||
|
|
|
@ -62,10 +62,10 @@ func (l *Listener) handleRedir(conn net.Conn, in chan<- C.ConnContext) {
|
||||||
|
|
||||||
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-REDIR",
|
inbound.WithInName("DEFAULT-REDIR"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := net.Listen("tcp", addr)
|
l, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
17
listener/config/shadowsocks.go
Normal file
17
listener/config/shadowsocks.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShadowsocksServer struct {
|
||||||
|
Enable bool
|
||||||
|
Listen string
|
||||||
|
Password string
|
||||||
|
Cipher string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t ShadowsocksServer) String() string {
|
||||||
|
b, _ := json.Marshal(t)
|
||||||
|
return string(b)
|
||||||
|
}
|
22
listener/config/vmess.go
Normal file
22
listener/config/vmess.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VmessUser struct {
|
||||||
|
Username string
|
||||||
|
UUID string
|
||||||
|
AlterID int
|
||||||
|
}
|
||||||
|
|
||||||
|
type VmessServer struct {
|
||||||
|
Enable bool
|
||||||
|
Listen string
|
||||||
|
Users []VmessUser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t VmessServer) String() string {
|
||||||
|
b, _ := json.Marshal(t)
|
||||||
|
return string(b)
|
||||||
|
}
|
|
@ -36,10 +36,10 @@ func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*
|
||||||
|
|
||||||
func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool, additions ...inbound.Addition) (*Listener, error) {
|
func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool, additions ...inbound.Addition) (*Listener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-HTTP",
|
inbound.WithInName("DEFAULT-HTTP"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := inbound.Listen("tcp", addr)
|
l, err := inbound.Listen("tcp", addr)
|
||||||
|
|
||||||
|
|
|
@ -87,10 +87,10 @@ func (o BaseOption) Equal(config C.InboundConfig) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o BaseOption) Additions() []inbound.Addition {
|
func (o BaseOption) Additions() []inbound.Addition {
|
||||||
return []inbound.Addition{{
|
return []inbound.Addition{
|
||||||
InName: o.NameStr,
|
inbound.WithInName(o.NameStr),
|
||||||
SpecialRules: o.SpecialRules,
|
inbound.WithSpecialRules(o.SpecialRules),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ C.InboundConfig = (*BaseOption)(nil)
|
var _ C.InboundConfig = (*BaseOption)(nil)
|
||||||
|
|
79
listener/inbound/shadowsocks.go
Normal file
79
listener/inbound/shadowsocks.go
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package inbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
LC "github.com/Dreamacro/clash/listener/config"
|
||||||
|
"github.com/Dreamacro/clash/listener/sing_shadowsocks"
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShadowSocksOption struct {
|
||||||
|
BaseOption
|
||||||
|
Password string `inbound:"password"`
|
||||||
|
Cipher string `inbound:"cipher"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ShadowSocksOption) Equal(config C.InboundConfig) bool {
|
||||||
|
return optionToString(o) == optionToString(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShadowSocks struct {
|
||||||
|
*Base
|
||||||
|
config *ShadowSocksOption
|
||||||
|
l C.MultiAddrListener
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShadowSocks(options *ShadowSocksOption) (*ShadowSocks, error) {
|
||||||
|
base, err := NewBase(&options.BaseOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ShadowSocks{
|
||||||
|
Base: base,
|
||||||
|
config: options,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config implements constant.InboundListener
|
||||||
|
func (s *ShadowSocks) Config() C.InboundConfig {
|
||||||
|
return s.config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address implements constant.InboundListener
|
||||||
|
func (s *ShadowSocks) Address() string {
|
||||||
|
if s.l != nil {
|
||||||
|
for _, addr := range s.l.AddrList() {
|
||||||
|
return addr.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen implements constant.InboundListener
|
||||||
|
func (s *ShadowSocks) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error {
|
||||||
|
var err error
|
||||||
|
s.l, err = sing_shadowsocks.New(
|
||||||
|
LC.ShadowsocksServer{
|
||||||
|
Enable: true,
|
||||||
|
Listen: s.RawAddress(),
|
||||||
|
Password: s.config.Password,
|
||||||
|
Cipher: s.config.Cipher,
|
||||||
|
},
|
||||||
|
tcpIn,
|
||||||
|
udpIn,
|
||||||
|
s.Additions()...,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infoln("ShadowSocks[%s] proxy listening at: %s", s.Name(), s.Address())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close implements constant.InboundListener
|
||||||
|
func (s *ShadowSocks) Close() error {
|
||||||
|
return s.l.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ C.InboundListener = (*ShadowSocks)(nil)
|
91
listener/inbound/vmess.go
Normal file
91
listener/inbound/vmess.go
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package inbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
LC "github.com/Dreamacro/clash/listener/config"
|
||||||
|
"github.com/Dreamacro/clash/listener/sing_vmess"
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VmessOption struct {
|
||||||
|
BaseOption
|
||||||
|
Users []VmessUser `inbound:"users"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VmessUser struct {
|
||||||
|
Username string `inbound:"username,omitempty"`
|
||||||
|
UUID string `inbound:"uuid"`
|
||||||
|
AlterID int `inbound:"alterId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o VmessOption) Equal(config C.InboundConfig) bool {
|
||||||
|
return optionToString(o) == optionToString(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Vmess struct {
|
||||||
|
*Base
|
||||||
|
config *VmessOption
|
||||||
|
l C.MultiAddrListener
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVmess(options *VmessOption) (*Vmess, error) {
|
||||||
|
base, err := NewBase(&options.BaseOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Vmess{
|
||||||
|
Base: base,
|
||||||
|
config: options,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config implements constant.InboundListener
|
||||||
|
func (v *Vmess) Config() C.InboundConfig {
|
||||||
|
return v.config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address implements constant.InboundListener
|
||||||
|
func (v *Vmess) Address() string {
|
||||||
|
if v.l != nil {
|
||||||
|
for _, addr := range v.l.AddrList() {
|
||||||
|
return addr.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen implements constant.InboundListener
|
||||||
|
func (v *Vmess) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error {
|
||||||
|
var err error
|
||||||
|
users := make([]LC.VmessUser, len(v.config.Users))
|
||||||
|
for i, v := range v.config.Users {
|
||||||
|
users[i] = LC.VmessUser{
|
||||||
|
Username: v.Username,
|
||||||
|
UUID: v.UUID,
|
||||||
|
AlterID: v.AlterID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.l, err = sing_vmess.New(
|
||||||
|
LC.VmessServer{
|
||||||
|
Enable: true,
|
||||||
|
Listen: v.RawAddress(),
|
||||||
|
Users: users,
|
||||||
|
},
|
||||||
|
tcpIn,
|
||||||
|
udpIn,
|
||||||
|
v.Additions()...,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infoln("Vmess[%s] proxy listening at: %s", v.Name(), v.Address())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close implements constant.InboundListener
|
||||||
|
func (v *Vmess) Close() error {
|
||||||
|
return v.l.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ C.InboundListener = (*Vmess)(nil)
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/Dreamacro/clash/listener/http"
|
"github.com/Dreamacro/clash/listener/http"
|
||||||
"github.com/Dreamacro/clash/listener/mixed"
|
"github.com/Dreamacro/clash/listener/mixed"
|
||||||
"github.com/Dreamacro/clash/listener/redir"
|
"github.com/Dreamacro/clash/listener/redir"
|
||||||
|
embedSS "github.com/Dreamacro/clash/listener/shadowsocks"
|
||||||
"github.com/Dreamacro/clash/listener/sing_shadowsocks"
|
"github.com/Dreamacro/clash/listener/sing_shadowsocks"
|
||||||
"github.com/Dreamacro/clash/listener/sing_tun"
|
"github.com/Dreamacro/clash/listener/sing_tun"
|
||||||
"github.com/Dreamacro/clash/listener/sing_vmess"
|
"github.com/Dreamacro/clash/listener/sing_vmess"
|
||||||
|
@ -45,7 +46,7 @@ var (
|
||||||
tunnelUDPListeners = map[string]*tunnel.PacketConn{}
|
tunnelUDPListeners = map[string]*tunnel.PacketConn{}
|
||||||
inboundListeners = map[string]C.InboundListener{}
|
inboundListeners = map[string]C.InboundListener{}
|
||||||
tunLister *sing_tun.Listener
|
tunLister *sing_tun.Listener
|
||||||
shadowSocksListener C.AdvanceListener
|
shadowSocksListener C.MultiAddrListener
|
||||||
vmessListener *sing_vmess.Listener
|
vmessListener *sing_vmess.Listener
|
||||||
tuicListener *tuic.Listener
|
tuicListener *tuic.Listener
|
||||||
autoRedirListener *autoredir.Listener
|
autoRedirListener *autoredir.Listener
|
||||||
|
@ -263,10 +264,20 @@ func ReCreateShadowSocks(shadowSocksConfig string, tcpIn chan<- C.ConnContext, u
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
var ssConfig LC.ShadowsocksServer
|
||||||
|
if addr, cipher, password, err := embedSS.ParseSSURL(shadowSocksConfig); err == nil {
|
||||||
|
ssConfig = LC.ShadowsocksServer{
|
||||||
|
Enable: true,
|
||||||
|
Listen: addr,
|
||||||
|
Password: password,
|
||||||
|
Cipher: cipher,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shouldIgnore := false
|
shouldIgnore := false
|
||||||
|
|
||||||
if shadowSocksListener != nil {
|
if shadowSocksListener != nil {
|
||||||
if shadowSocksListener.Config() != shadowSocksConfig {
|
if shadowSocksListener.Config() != ssConfig.String() {
|
||||||
shadowSocksListener.Close()
|
shadowSocksListener.Close()
|
||||||
shadowSocksListener = nil
|
shadowSocksListener = nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -278,17 +289,20 @@ func ReCreateShadowSocks(shadowSocksConfig string, tcpIn chan<- C.ConnContext, u
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(shadowSocksConfig) == 0 {
|
if !ssConfig.Enable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
listener, err := sing_shadowsocks.New(shadowSocksConfig, tcpIn, udpIn)
|
listener, err := sing_shadowsocks.New(ssConfig, tcpIn, udpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowSocksListener = listener
|
shadowSocksListener = listener
|
||||||
|
|
||||||
|
for _, addr := range shadowSocksListener.AddrList() {
|
||||||
|
log.Infoln("ShadowSocks proxy listening at: %s", addr.String())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,10 +317,19 @@ func ReCreateVmess(vmessConfig string, tcpIn chan<- C.ConnContext, udpIn chan<-
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
var vsConfig LC.VmessServer
|
||||||
|
if addr, username, password, err := sing_vmess.ParseVmessURL(vmessConfig); err == nil {
|
||||||
|
vsConfig = LC.VmessServer{
|
||||||
|
Enable: true,
|
||||||
|
Listen: addr,
|
||||||
|
Users: []LC.VmessUser{{Username: username, UUID: password, AlterID: 1}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shouldIgnore := false
|
shouldIgnore := false
|
||||||
|
|
||||||
if vmessListener != nil {
|
if vmessListener != nil {
|
||||||
if vmessListener.Config() != vmessConfig {
|
if vmessListener.Config() != vsConfig.String() {
|
||||||
vmessListener.Close()
|
vmessListener.Close()
|
||||||
vmessListener = nil
|
vmessListener = nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -318,17 +341,20 @@ func ReCreateVmess(vmessConfig string, tcpIn chan<- C.ConnContext, udpIn chan<-
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(vmessConfig) == 0 {
|
if !vsConfig.Enable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
listener, err := sing_vmess.New(vmessConfig, tcpIn, udpIn)
|
listener, err := sing_vmess.New(vsConfig, tcpIn, udpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
vmessListener = listener
|
vmessListener = listener
|
||||||
|
|
||||||
|
for _, addr := range vmessListener.AddrList() {
|
||||||
|
log.Infoln("Vmess proxy listening at: %s", addr.String())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,10 +38,10 @@ func (l *Listener) Close() error {
|
||||||
|
|
||||||
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-MIXED",
|
inbound.WithInName("DEFAULT-MIXED"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := inbound.Listen("tcp", addr)
|
l, err := inbound.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -55,6 +55,20 @@ func ParseListener(mapping map[string]any) (C.InboundListener, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
listener, err = IN.NewMixed(mixedOption)
|
listener, err = IN.NewMixed(mixedOption)
|
||||||
|
case "shadowsocks":
|
||||||
|
shadowsocksOption := &IN.ShadowSocksOption{}
|
||||||
|
err = decoder.Decode(mapping, shadowsocksOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listener, err = IN.NewShadowSocks(shadowsocksOption)
|
||||||
|
case "vmess":
|
||||||
|
vmessOption := &IN.VmessOption{}
|
||||||
|
err = decoder.Decode(mapping, vmessOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listener, err = IN.NewVmess(vmessOption)
|
||||||
case "tuic":
|
case "tuic":
|
||||||
tuicOption := &IN.TuicOption{
|
tuicOption := &IN.TuicOption{
|
||||||
MaxIdleTime: 15000,
|
MaxIdleTime: 15000,
|
||||||
|
|
|
@ -31,10 +31,10 @@ func (l *Listener) Close() error {
|
||||||
|
|
||||||
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-REDIR",
|
inbound.WithInName("DEFAULT-REDIR"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := net.Listen("tcp", addr)
|
l, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -6,14 +6,14 @@ import (
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/inbound"
|
"github.com/Dreamacro/clash/adapter/inbound"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
LC "github.com/Dreamacro/clash/listener/config"
|
||||||
"github.com/Dreamacro/clash/transport/shadowsocks/core"
|
"github.com/Dreamacro/clash/transport/shadowsocks/core"
|
||||||
"github.com/Dreamacro/clash/transport/socks5"
|
"github.com/Dreamacro/clash/transport/socks5"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
closed bool
|
closed bool
|
||||||
config string
|
config LC.ShadowsocksServer
|
||||||
listeners []net.Listener
|
listeners []net.Listener
|
||||||
udpListeners []*UDPListener
|
udpListeners []*UDPListener
|
||||||
pickCipher core.Cipher
|
pickCipher core.Cipher
|
||||||
|
@ -21,13 +21,8 @@ type Listener struct {
|
||||||
|
|
||||||
var _listener *Listener
|
var _listener *Listener
|
||||||
|
|
||||||
func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) (*Listener, error) {
|
func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) (*Listener, error) {
|
||||||
addr, cipher, password, err := ParseSSURL(config)
|
pickCipher, err := core.PickCipher(config.Cipher, nil, config.Password)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pickCipher, err := core.PickCipher(cipher, nil, password)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -35,7 +30,7 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter
|
||||||
sl := &Listener{false, config, nil, nil, pickCipher}
|
sl := &Listener{false, config, nil, nil, pickCipher}
|
||||||
_listener = sl
|
_listener = sl
|
||||||
|
|
||||||
for _, addr := range strings.Split(addr, ",") {
|
for _, addr := range strings.Split(config.Listen, ",") {
|
||||||
addr := addr
|
addr := addr
|
||||||
|
|
||||||
//UDP
|
//UDP
|
||||||
|
@ -53,7 +48,6 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter
|
||||||
sl.listeners = append(sl.listeners, l)
|
sl.listeners = append(sl.listeners, l)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
log.Infoln("ShadowSocks proxy listening at: %s", l.Addr().String())
|
|
||||||
for {
|
for {
|
||||||
c, err := l.Accept()
|
c, err := l.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -89,7 +83,7 @@ func (l *Listener) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) Config() string {
|
func (l *Listener) Config() string {
|
||||||
return l.config
|
return l.config.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) AddrList() (addrList []net.Addr) {
|
func (l *Listener) AddrList() (addrList []net.Addr) {
|
||||||
|
@ -102,7 +96,7 @@ func (l *Listener) AddrList() (addrList []net.Addr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) {
|
func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) {
|
||||||
conn = l.pickCipher.StreamConn(conn)
|
conn = l.pickCipher.StreamConn(conn)
|
||||||
|
|
||||||
target, err := socks5.ReadAddr(conn, make([]byte, socks5.MaxAddrLen))
|
target, err := socks5.ReadAddr(conn, make([]byte, socks5.MaxAddrLen))
|
||||||
|
@ -110,12 +104,12 @@ func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) {
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
in <- inbound.NewSocket(target, conn, C.SHADOWSOCKS)
|
in <- inbound.NewSocket(target, conn, C.SHADOWSOCKS, additions...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleShadowSocks(conn net.Conn, in chan<- C.ConnContext) bool {
|
func HandleShadowSocks(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) bool {
|
||||||
if _listener != nil && _listener.pickCipher != nil {
|
if _listener != nil && _listener.pickCipher != nil {
|
||||||
go _listener.HandleConn(conn, in)
|
go _listener.HandleConn(conn, in, additions...)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
24
listener/sing/context.go
Normal file
24
listener/sing/context.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package sing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/adapter/inbound"
|
||||||
|
)
|
||||||
|
|
||||||
|
type contextKey string
|
||||||
|
|
||||||
|
var ctxKeyAdditions = contextKey("Additions")
|
||||||
|
|
||||||
|
func WithAdditions(ctx context.Context, additions ...inbound.Addition) context.Context {
|
||||||
|
return context.WithValue(ctx, ctxKeyAdditions, additions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAdditions(ctx context.Context) []inbound.Addition {
|
||||||
|
if v := ctx.Value(ctxKeyAdditions); v != nil {
|
||||||
|
if a, ok := v.([]inbound.Addition); ok {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package sing
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -23,9 +24,10 @@ import (
|
||||||
const UDPTimeout = 5 * time.Minute
|
const UDPTimeout = 5 * time.Minute
|
||||||
|
|
||||||
type ListenerHandler struct {
|
type ListenerHandler struct {
|
||||||
TcpIn chan<- C.ConnContext
|
TcpIn chan<- C.ConnContext
|
||||||
UdpIn chan<- C.PacketAdapter
|
UdpIn chan<- C.PacketAdapter
|
||||||
Type C.Type
|
Type C.Type
|
||||||
|
Additions []inbound.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
type waitCloseConn struct {
|
type waitCloseConn struct {
|
||||||
|
@ -47,6 +49,11 @@ func (c *waitCloseConn) RemoteAddr() net.Addr {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||||
|
additions := h.Additions
|
||||||
|
if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 {
|
||||||
|
additions = slices.Clone(additions)
|
||||||
|
additions = append(additions, ctxAdditions...)
|
||||||
|
}
|
||||||
switch metadata.Destination.Fqdn {
|
switch metadata.Destination.Fqdn {
|
||||||
case vmess.MuxDestination.Fqdn:
|
case vmess.MuxDestination.Fqdn:
|
||||||
return vmess.HandleMuxConnection(ctx, conn, h)
|
return vmess.HandleMuxConnection(ctx, conn, h)
|
||||||
|
@ -58,11 +65,17 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
defer wg.Wait() // this goroutine must exit after conn.Close()
|
defer wg.Wait() // this goroutine must exit after conn.Close()
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
h.TcpIn <- inbound.NewSocket(target, &waitCloseConn{Conn: conn, wg: wg, rAddr: metadata.Source.TCPAddr()}, h.Type)
|
|
||||||
|
h.TcpIn <- inbound.NewSocket(target, &waitCloseConn{Conn: conn, wg: wg, rAddr: metadata.Source.TCPAddr()}, h.Type, additions...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error {
|
func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error {
|
||||||
|
additions := h.Additions
|
||||||
|
if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 {
|
||||||
|
additions = slices.Clone(additions)
|
||||||
|
additions = append(additions, ctxAdditions...)
|
||||||
|
}
|
||||||
defer func() { _ = conn.Close() }()
|
defer func() { _ = conn.Close() }()
|
||||||
mutex := sync.Mutex{}
|
mutex := sync.Mutex{}
|
||||||
conn2 := conn // a new interface to set nil in defer
|
conn2 := conn // a new interface to set nil in defer
|
||||||
|
@ -90,7 +103,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
|
||||||
buff: buff,
|
buff: buff,
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case h.UdpIn <- inbound.NewPacket(target, packet, h.Type):
|
case h.UdpIn <- inbound.NewPacket(target, packet, h.Type, additions...):
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/Dreamacro/clash/adapter/inbound"
|
"github.com/Dreamacro/clash/adapter/inbound"
|
||||||
"github.com/Dreamacro/clash/common/sockopt"
|
"github.com/Dreamacro/clash/common/sockopt"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
LC "github.com/Dreamacro/clash/listener/config"
|
||||||
embedSS "github.com/Dreamacro/clash/listener/shadowsocks"
|
embedSS "github.com/Dreamacro/clash/listener/shadowsocks"
|
||||||
"github.com/Dreamacro/clash/listener/sing"
|
"github.com/Dreamacro/clash/listener/sing"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
@ -24,7 +25,7 @@ import (
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
closed bool
|
closed bool
|
||||||
config string
|
config LC.ShadowsocksServer
|
||||||
listeners []net.Listener
|
listeners []net.Listener
|
||||||
udpListeners []net.PacketConn
|
udpListeners []net.PacketConn
|
||||||
service shadowsocks.Service
|
service shadowsocks.Service
|
||||||
|
@ -32,39 +33,46 @@ type Listener struct {
|
||||||
|
|
||||||
var _listener *Listener
|
var _listener *Listener
|
||||||
|
|
||||||
func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) (C.AdvanceListener, error) {
|
func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter, additions ...inbound.Addition) (C.MultiAddrListener, error) {
|
||||||
addr, cipher, password, err := embedSS.ParseSSURL(config)
|
var sl *Listener
|
||||||
if err != nil {
|
var err error
|
||||||
return nil, err
|
if len(additions) == 0 {
|
||||||
|
additions = []inbound.Addition{
|
||||||
|
inbound.WithInName("DEFAULT-SHADOWSOCKS"),
|
||||||
|
inbound.WithSpecialRules(""),
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_listener = sl
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
udpTimeout := int64(sing.UDPTimeout.Seconds())
|
udpTimeout := int64(sing.UDPTimeout.Seconds())
|
||||||
|
|
||||||
h := &sing.ListenerHandler{
|
h := &sing.ListenerHandler{
|
||||||
TcpIn: tcpIn,
|
TcpIn: tcpIn,
|
||||||
UdpIn: udpIn,
|
UdpIn: udpIn,
|
||||||
Type: C.SHADOWSOCKS,
|
Type: C.SHADOWSOCKS,
|
||||||
|
Additions: additions,
|
||||||
}
|
}
|
||||||
|
|
||||||
sl := &Listener{false, config, nil, nil, nil}
|
sl = &Listener{false, config, nil, nil, nil}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cipher == shadowsocks.MethodNone:
|
case config.Cipher == shadowsocks.MethodNone:
|
||||||
sl.service = shadowsocks.NewNoneService(udpTimeout, h)
|
sl.service = shadowsocks.NewNoneService(udpTimeout, h)
|
||||||
case common.Contains(shadowaead.List, cipher):
|
case common.Contains(shadowaead.List, config.Cipher):
|
||||||
sl.service, err = shadowaead.NewService(cipher, nil, password, udpTimeout, h)
|
sl.service, err = shadowaead.NewService(config.Cipher, nil, config.Password, udpTimeout, h)
|
||||||
case common.Contains(shadowaead_2022.List, cipher):
|
case common.Contains(shadowaead_2022.List, config.Cipher):
|
||||||
sl.service, err = shadowaead_2022.NewServiceWithPassword(cipher, password, udpTimeout, h)
|
sl.service, err = shadowaead_2022.NewServiceWithPassword(config.Cipher, config.Password, udpTimeout, h)
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("shadowsocks: unsupported method: %s", cipher)
|
err = fmt.Errorf("shadowsocks: unsupported method: %s", config.Cipher)
|
||||||
return embedSS.New(config, tcpIn, udpIn)
|
return embedSS.New(config, tcpIn, udpIn)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_listener = sl
|
for _, addr := range strings.Split(config.Listen, ",") {
|
||||||
|
|
||||||
for _, addr := range strings.Split(addr, ",") {
|
|
||||||
addr := addr
|
addr := addr
|
||||||
|
|
||||||
//UDP
|
//UDP
|
||||||
|
@ -107,7 +115,6 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter
|
||||||
sl.listeners = append(sl.listeners, l)
|
sl.listeners = append(sl.listeners, l)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
log.Infoln("ShadowSocks proxy listening at: %s", l.Addr().String())
|
|
||||||
for {
|
for {
|
||||||
c, err := l.Accept()
|
c, err := l.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -145,7 +152,7 @@ func (l *Listener) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) Config() string {
|
func (l *Listener) Config() string {
|
||||||
return l.config
|
return l.config.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) AddrList() (addrList []net.Addr) {
|
func (l *Listener) AddrList() (addrList []net.Addr) {
|
||||||
|
@ -158,8 +165,9 @@ func (l *Listener) AddrList() (addrList []net.Addr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) {
|
func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) {
|
||||||
err := l.service.NewConnection(context.TODO(), conn, metadata.Metadata{
|
ctx := sing.WithAdditions(context.TODO(), additions...)
|
||||||
|
err := l.service.NewConnection(ctx, conn, metadata.Metadata{
|
||||||
Protocol: "shadowsocks",
|
Protocol: "shadowsocks",
|
||||||
Source: metadata.ParseSocksaddr(conn.RemoteAddr().String()),
|
Source: metadata.ParseSocksaddr(conn.RemoteAddr().String()),
|
||||||
})
|
})
|
||||||
|
@ -169,10 +177,10 @@ func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleShadowSocks(conn net.Conn, in chan<- C.ConnContext) bool {
|
func HandleShadowSocks(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) bool {
|
||||||
if _listener != nil && _listener.service != nil {
|
if _listener != nil && _listener.service != nil {
|
||||||
go _listener.HandleConn(conn, in)
|
go _listener.HandleConn(conn, in, additions...)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return embedSS.HandleShadowSocks(conn, in)
|
return embedSS.HandleShadowSocks(conn, in, additions...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,36 +8,51 @@ import (
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/inbound"
|
"github.com/Dreamacro/clash/adapter/inbound"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
LC "github.com/Dreamacro/clash/listener/config"
|
||||||
"github.com/Dreamacro/clash/listener/sing"
|
"github.com/Dreamacro/clash/listener/sing"
|
||||||
"github.com/Dreamacro/clash/log"
|
|
||||||
|
|
||||||
vmess "github.com/sagernet/sing-vmess"
|
vmess "github.com/sagernet/sing-vmess"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/metadata"
|
"github.com/sagernet/sing/common/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
closed bool
|
closed bool
|
||||||
config string
|
config LC.VmessServer
|
||||||
listeners []net.Listener
|
listeners []net.Listener
|
||||||
service *vmess.Service[string]
|
service *vmess.Service[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
var _listener *Listener
|
var _listener *Listener
|
||||||
|
|
||||||
func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) (*Listener, error) {
|
func New(config LC.VmessServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter, additions ...inbound.Addition) (sl *Listener, err error) {
|
||||||
addr, username, password, err := parseVmessURL(config)
|
if len(additions) == 0 {
|
||||||
if err != nil {
|
additions = []inbound.Addition{
|
||||||
return nil, err
|
inbound.WithInName("DEFAULT-VMESS"),
|
||||||
|
inbound.WithSpecialRules(""),
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_listener = sl
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
h := &sing.ListenerHandler{
|
h := &sing.ListenerHandler{
|
||||||
TcpIn: tcpIn,
|
TcpIn: tcpIn,
|
||||||
UdpIn: udpIn,
|
UdpIn: udpIn,
|
||||||
Type: C.VMESS,
|
Type: C.VMESS,
|
||||||
|
Additions: additions,
|
||||||
}
|
}
|
||||||
|
|
||||||
service := vmess.NewService[string](h)
|
service := vmess.NewService[string](h)
|
||||||
err = service.UpdateUsers([]string{username}, []string{password}, []int{1})
|
err = service.UpdateUsers(
|
||||||
|
common.Map(config.Users, func(it LC.VmessUser) string {
|
||||||
|
return it.Username
|
||||||
|
}),
|
||||||
|
common.Map(config.Users, func(it LC.VmessUser) string {
|
||||||
|
return it.UUID
|
||||||
|
}),
|
||||||
|
common.Map(config.Users, func(it LC.VmessUser) int {
|
||||||
|
return it.AlterID
|
||||||
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -47,10 +62,9 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sl := &Listener{false, config, nil, service}
|
sl = &Listener{false, config, nil, service}
|
||||||
_listener = sl
|
|
||||||
|
|
||||||
for _, addr := range strings.Split(addr, ",") {
|
for _, addr := range strings.Split(config.Listen, ",") {
|
||||||
addr := addr
|
addr := addr
|
||||||
|
|
||||||
//TCP
|
//TCP
|
||||||
|
@ -61,7 +75,6 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter
|
||||||
sl.listeners = append(sl.listeners, l)
|
sl.listeners = append(sl.listeners, l)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
log.Infoln("Vmess proxy listening at: %s", l.Addr().String())
|
|
||||||
for {
|
for {
|
||||||
c, err := l.Accept()
|
c, err := l.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -97,7 +110,7 @@ func (l *Listener) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) Config() string {
|
func (l *Listener) Config() string {
|
||||||
return l.config
|
return l.config.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) AddrList() (addrList []net.Addr) {
|
func (l *Listener) AddrList() (addrList []net.Addr) {
|
||||||
|
@ -107,8 +120,9 @@ func (l *Listener) AddrList() (addrList []net.Addr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) {
|
func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) {
|
||||||
err := l.service.NewConnection(context.TODO(), conn, metadata.Metadata{
|
ctx := sing.WithAdditions(context.TODO(), additions...)
|
||||||
|
err := l.service.NewConnection(ctx, conn, metadata.Metadata{
|
||||||
Protocol: "vmess",
|
Protocol: "vmess",
|
||||||
Source: metadata.ParseSocksaddr(conn.RemoteAddr().String()),
|
Source: metadata.ParseSocksaddr(conn.RemoteAddr().String()),
|
||||||
})
|
})
|
||||||
|
@ -118,15 +132,15 @@ func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleVmess(conn net.Conn, in chan<- C.ConnContext) bool {
|
func HandleVmess(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) bool {
|
||||||
if _listener != nil && _listener.service != nil {
|
if _listener != nil && _listener.service != nil {
|
||||||
go _listener.HandleConn(conn, in)
|
go _listener.HandleConn(conn, in, additions...)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseVmessURL(s string) (addr, username, password string, err error) {
|
func ParseVmessURL(s string) (addr, username, password string, err error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -36,10 +36,10 @@ func (l *Listener) Close() error {
|
||||||
|
|
||||||
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-SOCKS",
|
inbound.WithInName("DEFAULT-SOCKS"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := inbound.Listen("tcp", addr)
|
l, err := inbound.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -35,10 +35,10 @@ func (l *UDPListener) Close() error {
|
||||||
|
|
||||||
func NewUDP(addr string, in chan<- C.PacketAdapter, additions ...inbound.Addition) (*UDPListener, error) {
|
func NewUDP(addr string, in chan<- C.PacketAdapter, additions ...inbound.Addition) (*UDPListener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-SOCKS",
|
inbound.WithInName("DEFAULT-SOCKS"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := net.ListenPacket("udp", addr)
|
l, err := net.ListenPacket("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -38,10 +38,10 @@ func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext, addition
|
||||||
|
|
||||||
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-TPROXY",
|
inbound.WithInName("DEFAULT-TPROXY"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := net.Listen("tcp", addr)
|
l, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -34,10 +34,10 @@ func (l *UDPListener) Close() error {
|
||||||
|
|
||||||
func NewUDP(addr string, in chan<- C.PacketAdapter, additions ...inbound.Addition) (*UDPListener, error) {
|
func NewUDP(addr string, in chan<- C.PacketAdapter, additions ...inbound.Addition) (*UDPListener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-TPROXY",
|
inbound.WithInName("DEFAULT-TPROXY"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
l, err := net.ListenPacket("udp", addr)
|
l, err := net.ListenPacket("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -27,10 +27,10 @@ type Listener struct {
|
||||||
|
|
||||||
func New(config LC.TuicServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter, additions ...inbound.Addition) (*Listener, error) {
|
func New(config LC.TuicServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter, additions ...inbound.Addition) (*Listener, error) {
|
||||||
if len(additions) == 0 {
|
if len(additions) == 0 {
|
||||||
additions = []inbound.Addition{{
|
additions = []inbound.Addition{
|
||||||
InName: "DEFAULT-TUIC",
|
inbound.WithInName("DEFAULT-TUIC"),
|
||||||
SpecialRules: "",
|
inbound.WithSpecialRules(""),
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
cert, err := CN.ParseCert(config.Certificate, config.PrivateKey)
|
cert, err := CN.ParseCert(config.Certificate, config.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue