github.com/chwjbn/xclash@v0.2.0/listener/listener.go (about) 1 package proxy 2 3 import ( 4 "fmt" 5 "net" 6 "strconv" 7 "sync" 8 9 "github.com/chwjbn/xclash/adapter/inbound" 10 C "github.com/chwjbn/xclash/constant" 11 "github.com/chwjbn/xclash/listener/http" 12 "github.com/chwjbn/xclash/listener/mixed" 13 "github.com/chwjbn/xclash/listener/redir" 14 "github.com/chwjbn/xclash/listener/socks" 15 "github.com/chwjbn/xclash/listener/tproxy" 16 "github.com/chwjbn/xclash/log" 17 ) 18 19 var ( 20 allowLan = false 21 bindAddress = "*" 22 23 socksListener *socks.Listener 24 socksUDPListener *socks.UDPListener 25 httpListener *http.Listener 26 redirListener *redir.Listener 27 redirUDPListener *tproxy.UDPListener 28 tproxyListener *tproxy.Listener 29 tproxyUDPListener *tproxy.UDPListener 30 mixedListener *mixed.Listener 31 mixedUDPLister *socks.UDPListener 32 33 // lock for recreate function 34 socksMux sync.Mutex 35 httpMux sync.Mutex 36 redirMux sync.Mutex 37 tproxyMux sync.Mutex 38 mixedMux sync.Mutex 39 ) 40 41 type Ports struct { 42 Port int `json:"port"` 43 SocksPort int `json:"socks-port"` 44 RedirPort int `json:"redir-port"` 45 TProxyPort int `json:"tproxy-port"` 46 MixedPort int `json:"mixed-port"` 47 } 48 49 func AllowLan() bool { 50 return allowLan 51 } 52 53 func BindAddress() string { 54 return bindAddress 55 } 56 57 func SetAllowLan(al bool) { 58 allowLan = al 59 } 60 61 func SetBindAddress(host string) { 62 bindAddress = host 63 } 64 65 func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) { 66 httpMux.Lock() 67 defer httpMux.Unlock() 68 69 var err error 70 defer func() { 71 if err != nil { 72 log.Errorln("Start HTTP server error: %s", err.Error()) 73 } 74 }() 75 76 addr := genAddr(bindAddress, port, allowLan) 77 78 if httpListener != nil { 79 if httpListener.RawAddress() == addr { 80 return 81 } 82 httpListener.Close() 83 httpListener = nil 84 } 85 86 if portIsZero(addr) { 87 return 88 } 89 90 httpListener, err = http.New(addr, tcpIn) 91 if err != nil { 92 return 93 } 94 95 log.Infoln("HTTP proxy listening at: %s", httpListener.Address()) 96 } 97 98 func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 99 socksMux.Lock() 100 defer socksMux.Unlock() 101 102 var err error 103 defer func() { 104 if err != nil { 105 log.Errorln("Start SOCKS server error: %s", err.Error()) 106 } 107 }() 108 109 addr := genAddr(bindAddress, port, allowLan) 110 111 shouldTCPIgnore := false 112 shouldUDPIgnore := false 113 114 if socksListener != nil { 115 if socksListener.RawAddress() != addr { 116 socksListener.Close() 117 socksListener = nil 118 } else { 119 shouldTCPIgnore = true 120 } 121 } 122 123 if socksUDPListener != nil { 124 if socksUDPListener.RawAddress() != addr { 125 socksUDPListener.Close() 126 socksUDPListener = nil 127 } else { 128 shouldUDPIgnore = true 129 } 130 } 131 132 if shouldTCPIgnore && shouldUDPIgnore { 133 return 134 } 135 136 if portIsZero(addr) { 137 return 138 } 139 140 tcpListener, err := socks.New(addr, tcpIn) 141 if err != nil { 142 return 143 } 144 145 udpListener, err := socks.NewUDP(addr, udpIn) 146 if err != nil { 147 tcpListener.Close() 148 return 149 } 150 151 socksListener = tcpListener 152 socksUDPListener = udpListener 153 154 log.Infoln("SOCKS proxy listening at: %s", socksListener.Address()) 155 } 156 157 func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 158 redirMux.Lock() 159 defer redirMux.Unlock() 160 161 var err error 162 defer func() { 163 if err != nil { 164 log.Errorln("Start Redir server error: %s", err.Error()) 165 } 166 }() 167 168 addr := genAddr(bindAddress, port, allowLan) 169 170 if redirListener != nil { 171 if redirListener.RawAddress() == addr { 172 return 173 } 174 redirListener.Close() 175 redirListener = nil 176 } 177 178 if redirUDPListener != nil { 179 if redirUDPListener.RawAddress() == addr { 180 return 181 } 182 redirUDPListener.Close() 183 redirUDPListener = nil 184 } 185 186 if portIsZero(addr) { 187 return 188 } 189 190 redirListener, err = redir.New(addr, tcpIn) 191 if err != nil { 192 return 193 } 194 195 redirUDPListener, err = tproxy.NewUDP(addr, udpIn) 196 if err != nil { 197 log.Warnln("Failed to start Redir UDP Listener: %s", err) 198 } 199 200 log.Infoln("Redirect proxy listening at: %s", redirListener.Address()) 201 } 202 203 func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 204 tproxyMux.Lock() 205 defer tproxyMux.Unlock() 206 207 var err error 208 defer func() { 209 if err != nil { 210 log.Errorln("Start TProxy server error: %s", err.Error()) 211 } 212 }() 213 214 addr := genAddr(bindAddress, port, allowLan) 215 216 if tproxyListener != nil { 217 if tproxyListener.RawAddress() == addr { 218 return 219 } 220 tproxyListener.Close() 221 tproxyListener = nil 222 } 223 224 if tproxyUDPListener != nil { 225 if tproxyUDPListener.RawAddress() == addr { 226 return 227 } 228 tproxyUDPListener.Close() 229 tproxyUDPListener = nil 230 } 231 232 if portIsZero(addr) { 233 return 234 } 235 236 tproxyListener, err = tproxy.New(addr, tcpIn) 237 if err != nil { 238 return 239 } 240 241 tproxyUDPListener, err = tproxy.NewUDP(addr, udpIn) 242 if err != nil { 243 log.Warnln("Failed to start TProxy UDP Listener: %s", err) 244 } 245 246 log.Infoln("TProxy server listening at: %s", tproxyListener.Address()) 247 } 248 249 func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 250 mixedMux.Lock() 251 defer mixedMux.Unlock() 252 253 var err error 254 defer func() { 255 if err != nil { 256 log.Errorln("Start Mixed(http+socks) server error: %s", err.Error()) 257 } 258 }() 259 260 addr := genAddr(bindAddress, port, allowLan) 261 262 shouldTCPIgnore := false 263 shouldUDPIgnore := false 264 265 if mixedListener != nil { 266 if mixedListener.RawAddress() != addr { 267 mixedListener.Close() 268 mixedListener = nil 269 } else { 270 shouldTCPIgnore = true 271 } 272 } 273 if mixedUDPLister != nil { 274 if mixedUDPLister.RawAddress() != addr { 275 mixedUDPLister.Close() 276 mixedUDPLister = nil 277 } else { 278 shouldUDPIgnore = true 279 } 280 } 281 282 if shouldTCPIgnore && shouldUDPIgnore { 283 return 284 } 285 286 if portIsZero(addr) { 287 return 288 } 289 290 mixedListener, err = mixed.New(addr, tcpIn) 291 if err != nil { 292 return 293 } 294 295 mixedUDPLister, err = socks.NewUDP(addr, udpIn) 296 if err != nil { 297 mixedListener.Close() 298 return 299 } 300 301 log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address()) 302 } 303 304 // GetPorts return the ports of proxy servers 305 func GetPorts() *Ports { 306 ports := &Ports{} 307 308 if httpListener != nil { 309 _, portStr, _ := net.SplitHostPort(httpListener.Address()) 310 port, _ := strconv.Atoi(portStr) 311 ports.Port = port 312 } 313 314 if socksListener != nil { 315 _, portStr, _ := net.SplitHostPort(socksListener.Address()) 316 port, _ := strconv.Atoi(portStr) 317 ports.SocksPort = port 318 } 319 320 if redirListener != nil { 321 _, portStr, _ := net.SplitHostPort(redirListener.Address()) 322 port, _ := strconv.Atoi(portStr) 323 ports.RedirPort = port 324 } 325 326 if tproxyListener != nil { 327 _, portStr, _ := net.SplitHostPort(tproxyListener.Address()) 328 port, _ := strconv.Atoi(portStr) 329 ports.TProxyPort = port 330 } 331 332 if mixedListener != nil { 333 _, portStr, _ := net.SplitHostPort(mixedListener.Address()) 334 port, _ := strconv.Atoi(portStr) 335 ports.MixedPort = port 336 } 337 338 return ports 339 } 340 341 func portIsZero(addr string) bool { 342 _, port, err := net.SplitHostPort(addr) 343 if port == "0" || port == "" || err != nil { 344 return true 345 } 346 return false 347 } 348 349 func genAddr(host string, port int, allowLan bool) string { 350 if allowLan { 351 if host == "*" { 352 return fmt.Sprintf(":%d", port) 353 } 354 return fmt.Sprintf("%s:%d", host, port) 355 } 356 357 return fmt.Sprintf("127.0.0.1:%d", port) 358 }