github.com/xmplusdev/xray-core@v1.8.10/proxy/wireguard/wireguard.go (about)

     1  package wireguard
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/netip"
     7  	"strings"
     8  
     9  	"github.com/xmplusdev/xray-core/common"
    10  	"github.com/xmplusdev/xray-core/common/log"
    11  	"golang.zx2c4.com/wireguard/device"
    12  )
    13  
    14  //go:generate go run github.com/xmplusdev/xray-core/common/errors/errorgen
    15  
    16  var wgLogger = &device.Logger{
    17  	Verbosef: func(format string, args ...any) {
    18  		log.Record(&log.GeneralMessage{
    19  			Severity: log.Severity_Debug,
    20  			Content:  fmt.Sprintf(format, args...),
    21  		})
    22  	},
    23  	Errorf: func(format string, args ...any) {
    24  		log.Record(&log.GeneralMessage{
    25  			Severity: log.Severity_Error,
    26  			Content:  fmt.Sprintf(format, args...),
    27  		})
    28  	},
    29  }
    30  
    31  func init() {
    32  	common.Must(common.RegisterConfig((*DeviceConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
    33  		deviceConfig := config.(*DeviceConfig)
    34  		if deviceConfig.IsClient {
    35  			return New(ctx, deviceConfig)
    36  		} else {
    37  			return NewServer(ctx, deviceConfig)
    38  		}
    39  	}))
    40  }
    41  
    42  // convert endpoint string to netip.Addr
    43  func parseEndpoints(conf *DeviceConfig) ([]netip.Addr, bool, bool, error) {
    44  	var hasIPv4, hasIPv6 bool
    45  
    46  	endpoints := make([]netip.Addr, len(conf.Endpoint))
    47  	for i, str := range conf.Endpoint {
    48  		var addr netip.Addr
    49  		if strings.Contains(str, "/") {
    50  			prefix, err := netip.ParsePrefix(str)
    51  			if err != nil {
    52  				return nil, false, false, err
    53  			}
    54  			addr = prefix.Addr()
    55  			if prefix.Bits() != addr.BitLen() {
    56  				return nil, false, false, newError("interface address subnet should be /32 for IPv4 and /128 for IPv6")
    57  			}
    58  		} else {
    59  			var err error
    60  			addr, err = netip.ParseAddr(str)
    61  			if err != nil {
    62  				return nil, false, false, err
    63  			}
    64  		}
    65  		endpoints[i] = addr
    66  
    67  		if addr.Is4() {
    68  			hasIPv4 = true
    69  		} else if addr.Is6() {
    70  			hasIPv6 = true
    71  		}
    72  	}
    73  
    74  	return endpoints, hasIPv4, hasIPv6, nil
    75  }
    76  
    77  // serialize the config into an IPC request
    78  func createIPCRequest(conf *DeviceConfig) string {
    79  	var request strings.Builder
    80  
    81  	request.WriteString(fmt.Sprintf("private_key=%s\n", conf.SecretKey))
    82  
    83  	if !conf.IsClient {
    84  		// placeholder, we'll handle actual port listening on Xray
    85  		request.WriteString("listen_port=1337\n")
    86  	}
    87  
    88  	for _, peer := range conf.Peers {
    89  		if peer.PublicKey != "" {
    90  			request.WriteString(fmt.Sprintf("public_key=%s\n", peer.PublicKey))
    91  		}
    92  
    93  		if peer.PreSharedKey != "" {
    94  			request.WriteString(fmt.Sprintf("preshared_key=%s\n", peer.PreSharedKey))
    95  		}
    96  
    97  		if peer.Endpoint != "" {
    98  			request.WriteString(fmt.Sprintf("endpoint=%s\n", peer.Endpoint))
    99  		}
   100  
   101  		for _, ip := range peer.AllowedIps {
   102  			request.WriteString(fmt.Sprintf("allowed_ip=%s\n", ip))
   103  		}
   104  
   105  		if peer.KeepAlive != 0 {
   106  			request.WriteString(fmt.Sprintf("persistent_keepalive_interval=%d\n", peer.KeepAlive))
   107  		}
   108  	}
   109  
   110  	return request.String()[:request.Len()]
   111  }