github.com/TeaOSLab/EdgeNode@v1.3.8/internal/nodes/origin_utils.go (about)

     1  package nodes
     2  
     3  import (
     4  	"crypto/tls"
     5  	"errors"
     6  	"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
     7  	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
     8  	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
     9  	"github.com/iwind/TeaGo/types"
    10  	"net"
    11  	"strconv"
    12  )
    13  
    14  // OriginConnect 连接源站
    15  func OriginConnect(origin *serverconfigs.OriginConfig, serverPort int, remoteAddr string, tlsHost string) (originConn net.Conn, originAddr string, err error) {
    16  	if origin.Addr == nil {
    17  		return nil, "", errors.New("origin server address should not be empty")
    18  	}
    19  
    20  	// 支持TOA的连接
    21  	// 这个条件很重要,如果没有传递remoteAddr,表示不使用TOA
    22  	if len(remoteAddr) > 0 {
    23  		var toaConfig = sharedTOAManager.Config()
    24  		if toaConfig != nil && toaConfig.IsOn {
    25  			var retries = 3
    26  			for i := 1; i <= retries; i++ {
    27  				var port = int(toaConfig.RandLocalPort())
    28  				err = sharedTOAManager.SendMsg("add:" + strconv.Itoa(port) + ":" + remoteAddr)
    29  				if err != nil {
    30  					remotelogs.Error("TOA", "add failed: "+err.Error())
    31  				} else {
    32  					var dialer = net.Dialer{
    33  						Timeout: origin.ConnTimeoutDuration(),
    34  						LocalAddr: &net.TCPAddr{
    35  							Port: port,
    36  						},
    37  					}
    38  					originAddr = origin.Addr.PickAddress()
    39  
    40  					// 端口跟随
    41  					if origin.FollowPort && serverPort > 0 {
    42  						originAddr = configutils.QuoteIP(origin.Addr.Host) + ":" + types.String(serverPort)
    43  					}
    44  
    45  					var conn net.Conn
    46  					switch origin.Addr.Protocol {
    47  					case "", serverconfigs.ProtocolTCP, serverconfigs.ProtocolHTTP:
    48  						// TODO 支持TCP4/TCP6
    49  						// TODO 支持指定特定网卡
    50  						conn, err = dialer.Dial("tcp", originAddr)
    51  					case serverconfigs.ProtocolTLS, serverconfigs.ProtocolHTTPS:
    52  						// TODO 支持TCP4/TCP6
    53  						// TODO 支持指定特定网卡
    54  
    55  						var tlsConfig = &tls.Config{
    56  							InsecureSkipVerify: true,
    57  						}
    58  						if origin.Cert != nil {
    59  							var obj = origin.Cert.CertObject()
    60  							if obj != nil {
    61  								tlsConfig.InsecureSkipVerify = false
    62  								tlsConfig.Certificates = []tls.Certificate{*obj}
    63  								if len(origin.Cert.ServerName) > 0 {
    64  									tlsConfig.ServerName = origin.Cert.ServerName
    65  								}
    66  							}
    67  						}
    68  						if len(tlsHost) > 0 {
    69  							tlsConfig.ServerName = tlsHost
    70  						}
    71  
    72  						conn, err = tls.DialWithDialer(&dialer, "tcp", originAddr, tlsConfig)
    73  					}
    74  
    75  					// TODO 需要在合适的时机删除TOA记录
    76  					if err == nil || i == retries {
    77  						return conn, originAddr, err
    78  					}
    79  				}
    80  			}
    81  		}
    82  	}
    83  
    84  	originAddr = origin.Addr.PickAddress()
    85  
    86  	// 端口跟随
    87  	if origin.FollowPort && serverPort > 0 {
    88  		originAddr = configutils.QuoteIP(origin.Addr.Host) + ":" + types.String(serverPort)
    89  	}
    90  
    91  	switch origin.Addr.Protocol {
    92  	case "", serverconfigs.ProtocolTCP, serverconfigs.ProtocolHTTP:
    93  		// TODO 支持TCP4/TCP6
    94  		// TODO 支持指定特定网卡
    95  		originConn, err = net.DialTimeout("tcp", originAddr, origin.ConnTimeoutDuration())
    96  		return originConn, originAddr, err
    97  	case serverconfigs.ProtocolTLS, serverconfigs.ProtocolHTTPS:
    98  		// TODO 支持TCP4/TCP6
    99  		// TODO 支持指定特定网卡
   100  
   101  		var tlsConfig = &tls.Config{
   102  			InsecureSkipVerify: true,
   103  		}
   104  		if origin.Cert != nil {
   105  			var obj = origin.Cert.CertObject()
   106  			if obj != nil {
   107  				tlsConfig.InsecureSkipVerify = false
   108  				tlsConfig.Certificates = []tls.Certificate{*obj}
   109  				if len(origin.Cert.ServerName) > 0 {
   110  					tlsConfig.ServerName = origin.Cert.ServerName
   111  				}
   112  			}
   113  		}
   114  		if len(tlsHost) > 0 {
   115  			tlsConfig.ServerName = tlsHost
   116  		}
   117  
   118  		originConn, err = tls.Dial("tcp", originAddr, tlsConfig)
   119  		return originConn, originAddr, err
   120  	case serverconfigs.ProtocolUDP:
   121  		addr, err := net.ResolveUDPAddr("udp", originAddr)
   122  		if err != nil {
   123  			return nil, originAddr, err
   124  		}
   125  		originConn, err = net.DialUDP("udp", nil, addr)
   126  		return originConn, originAddr, err
   127  	}
   128  
   129  	// TODO 支持从Unix、Pipe、HTTP、HTTPS中读取数据
   130  
   131  	return nil, originAddr, errors.New("invalid origin scheme '" + origin.Addr.Protocol.String() + "'")
   132  }