github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/services/wireguard/service_config.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package wireguard
    19  
    20  import (
    21  	"encoding/json"
    22  	"net"
    23  )
    24  
    25  // ServiceType indicates "wireguard" service type
    26  const ServiceType = "wireguard"
    27  
    28  // ServiceConfig represent a Wireguard service provider configuration that will be passed to the consumer for establishing a connection.
    29  type ServiceConfig struct {
    30  	// LocalPort and RemotePort are needed for NAT hole punching only.
    31  	LocalPort  int   `json:"-"`
    32  	RemotePort int   `json:"-"`
    33  	Ports      []int `json:"ports"`
    34  
    35  	Provider struct {
    36  		PublicKey string
    37  		Endpoint  net.UDPAddr
    38  	}
    39  	Consumer struct {
    40  		IPAddress net.IPNet
    41  		DNSIPs    string
    42  	}
    43  }
    44  
    45  // ConsumerConfig is used for sending the public key and IP from consumer to provider.
    46  type ConsumerConfig struct {
    47  	PublicKey string `json:"PublicKey"`
    48  	// IP is needed when provider is behind NAT. In such case provider parses this IP and tries to ping consumer.
    49  	IP    string `json:"IP,omitempty"`
    50  	Ports []int  `json:"Ports"`
    51  }
    52  
    53  // MarshalJSON implements json.Marshaler interface to provide human readable configuration.
    54  func (s ServiceConfig) MarshalJSON() ([]byte, error) {
    55  	type provider struct {
    56  		PublicKey string `json:"public_key"`
    57  		Endpoint  string `json:"endpoint"`
    58  	}
    59  	type consumer struct {
    60  		IPAddress string `json:"ip_address"`
    61  		DNSIPs    string `json:"dns_ips"`
    62  	}
    63  
    64  	return json.Marshal(&struct {
    65  		LocalPort  int      `json:"local_port"`
    66  		RemotePort int      `json:"remote_port"`
    67  		Ports      []int    `json:"ports"`
    68  		Provider   provider `json:"provider"`
    69  		Consumer   consumer `json:"consumer"`
    70  	}{
    71  		Ports:      s.Ports,
    72  		LocalPort:  s.LocalPort,
    73  		RemotePort: s.RemotePort,
    74  		Provider: provider{
    75  			PublicKey: s.Provider.PublicKey,
    76  			Endpoint:  s.Provider.Endpoint.String(),
    77  		},
    78  		Consumer: consumer{
    79  			IPAddress: s.Consumer.IPAddress.String(),
    80  			DNSIPs:    s.Consumer.DNSIPs,
    81  		},
    82  	})
    83  }
    84  
    85  // UnmarshalJSON implements json.Unmarshaler interface to receive human readable configuration.
    86  func (s *ServiceConfig) UnmarshalJSON(data []byte) error {
    87  	type provider struct {
    88  		PublicKey string `json:"public_key"`
    89  		Endpoint  string `json:"endpoint"`
    90  	}
    91  	type consumer struct {
    92  		IPAddress string `json:"ip_address"`
    93  		DNSIPs    string `json:"dns_ips"`
    94  	}
    95  	var config struct {
    96  		LocalPort  int      `json:"local_port"`
    97  		RemotePort int      `json:"remote_port"`
    98  		Ports      []int    `json:"ports"`
    99  		Provider   provider `json:"provider"`
   100  		Consumer   consumer `json:"consumer"`
   101  	}
   102  
   103  	if err := json.Unmarshal(data, &config); err != nil {
   104  		return err
   105  	}
   106  
   107  	endpoint, err := net.ResolveUDPAddr("udp", config.Provider.Endpoint)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	ip, ipnet, err := net.ParseCIDR(config.Consumer.IPAddress)
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	s.Ports = config.Ports
   117  	s.LocalPort = config.LocalPort
   118  	s.RemotePort = config.RemotePort
   119  	s.Provider.Endpoint = *endpoint
   120  	s.Provider.PublicKey = config.Provider.PublicKey
   121  	s.Consumer.DNSIPs = config.Consumer.DNSIPs
   122  	s.Consumer.IPAddress = *ipnet
   123  	s.Consumer.IPAddress.IP = ip
   124  
   125  	return nil
   126  }