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  }