github.com/metacubex/mihomo@v1.18.5/listener/sing_vmess/server.go (about) 1 package sing_vmess 2 3 import ( 4 "context" 5 "crypto/tls" 6 "net" 7 "net/http" 8 "net/url" 9 "strings" 10 11 "github.com/metacubex/mihomo/adapter/inbound" 12 N "github.com/metacubex/mihomo/common/net" 13 C "github.com/metacubex/mihomo/constant" 14 LC "github.com/metacubex/mihomo/listener/config" 15 "github.com/metacubex/mihomo/listener/sing" 16 "github.com/metacubex/mihomo/ntp" 17 mihomoVMess "github.com/metacubex/mihomo/transport/vmess" 18 19 vmess "github.com/metacubex/sing-vmess" 20 "github.com/sagernet/sing/common" 21 "github.com/sagernet/sing/common/metadata" 22 ) 23 24 type Listener struct { 25 closed bool 26 config LC.VmessServer 27 listeners []net.Listener 28 service *vmess.Service[string] 29 } 30 31 var _listener *Listener 32 33 func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition) (sl *Listener, err error) { 34 if len(additions) == 0 { 35 additions = []inbound.Addition{ 36 inbound.WithInName("DEFAULT-VMESS"), 37 inbound.WithSpecialRules(""), 38 } 39 defer func() { 40 _listener = sl 41 }() 42 } 43 h, err := sing.NewListenerHandler(sing.ListenerConfig{ 44 Tunnel: tunnel, 45 Type: C.VMESS, 46 Additions: additions, 47 MuxOption: config.MuxOption, 48 }) 49 if err != nil { 50 return nil, err 51 } 52 53 service := vmess.NewService[string](h, vmess.ServiceWithDisableHeaderProtection(), vmess.ServiceWithTimeFunc(ntp.Now)) 54 err = service.UpdateUsers( 55 common.Map(config.Users, func(it LC.VmessUser) string { 56 return it.Username 57 }), 58 common.Map(config.Users, func(it LC.VmessUser) string { 59 return it.UUID 60 }), 61 common.Map(config.Users, func(it LC.VmessUser) int { 62 return it.AlterID 63 })) 64 if err != nil { 65 return nil, err 66 } 67 68 err = service.Start() 69 if err != nil { 70 return nil, err 71 } 72 73 sl = &Listener{false, config, nil, service} 74 75 tlsConfig := &tls.Config{} 76 var httpMux *http.ServeMux 77 78 if config.Certificate != "" && config.PrivateKey != "" { 79 cert, err := N.ParseCert(config.Certificate, config.PrivateKey, C.Path) 80 if err != nil { 81 return nil, err 82 } 83 tlsConfig.Certificates = []tls.Certificate{cert} 84 } 85 if config.WsPath != "" { 86 httpMux = http.NewServeMux() 87 httpMux.HandleFunc(config.WsPath, func(w http.ResponseWriter, r *http.Request) { 88 conn, err := mihomoVMess.StreamUpgradedWebsocketConn(w, r) 89 if err != nil { 90 http.Error(w, err.Error(), 500) 91 return 92 } 93 sl.HandleConn(conn, tunnel) 94 }) 95 tlsConfig.NextProtos = append(tlsConfig.NextProtos, "http/1.1") 96 } 97 98 for _, addr := range strings.Split(config.Listen, ",") { 99 addr := addr 100 101 //TCP 102 l, err := inbound.Listen("tcp", addr) 103 if err != nil { 104 return nil, err 105 } 106 if len(tlsConfig.Certificates) > 0 { 107 l = tls.NewListener(l, tlsConfig) 108 } 109 sl.listeners = append(sl.listeners, l) 110 111 go func() { 112 if httpMux != nil { 113 _ = http.Serve(l, httpMux) 114 return 115 } 116 for { 117 c, err := l.Accept() 118 if err != nil { 119 if sl.closed { 120 break 121 } 122 continue 123 } 124 N.TCPKeepAlive(c) 125 126 go sl.HandleConn(c, tunnel) 127 } 128 }() 129 } 130 131 return sl, nil 132 } 133 134 func (l *Listener) Close() error { 135 l.closed = true 136 var retErr error 137 for _, lis := range l.listeners { 138 err := lis.Close() 139 if err != nil { 140 retErr = err 141 } 142 } 143 err := l.service.Close() 144 if err != nil { 145 retErr = err 146 } 147 return retErr 148 } 149 150 func (l *Listener) Config() string { 151 return l.config.String() 152 } 153 154 func (l *Listener) AddrList() (addrList []net.Addr) { 155 for _, lis := range l.listeners { 156 addrList = append(addrList, lis.Addr()) 157 } 158 return 159 } 160 161 func (l *Listener) HandleConn(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { 162 ctx := sing.WithAdditions(context.TODO(), additions...) 163 err := l.service.NewConnection(ctx, conn, metadata.Metadata{ 164 Protocol: "vmess", 165 Source: metadata.ParseSocksaddr(conn.RemoteAddr().String()), 166 }) 167 if err != nil { 168 _ = conn.Close() 169 return 170 } 171 } 172 173 func HandleVmess(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) bool { 174 if _listener != nil && _listener.service != nil { 175 go _listener.HandleConn(conn, tunnel, additions...) 176 return true 177 } 178 return false 179 } 180 181 func ParseVmessURL(s string) (addr, username, password string, err error) { 182 u, err := url.Parse(s) 183 if err != nil { 184 return 185 } 186 187 addr = u.Host 188 if u.User != nil { 189 username = u.User.Username() 190 password, _ = u.User.Password() 191 } 192 return 193 }