github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/services/openvpn/service/manager.go (about) 1 /* 2 * Copyright (C) 2017 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 service 19 20 import ( 21 "encoding/json" 22 "errors" 23 "fmt" 24 "net" 25 26 "github.com/rs/zerolog/log" 27 28 "github.com/mysteriumnetwork/go-openvpn/openvpn" 29 "github.com/mysteriumnetwork/go-openvpn/openvpn/middlewares/server/filter" 30 "github.com/mysteriumnetwork/go-openvpn/openvpn/middlewares/state" 31 "github.com/mysteriumnetwork/go-openvpn/openvpn/tls" 32 "github.com/mysteriumnetwork/node/config" 33 "github.com/mysteriumnetwork/node/core/ip" 34 "github.com/mysteriumnetwork/node/core/node" 35 "github.com/mysteriumnetwork/node/core/port" 36 "github.com/mysteriumnetwork/node/core/service" 37 "github.com/mysteriumnetwork/node/core/shaper" 38 "github.com/mysteriumnetwork/node/dns" 39 "github.com/mysteriumnetwork/node/eventbus" 40 "github.com/mysteriumnetwork/node/firewall" 41 "github.com/mysteriumnetwork/node/identity" 42 "github.com/mysteriumnetwork/node/market" 43 "github.com/mysteriumnetwork/node/nat" 44 openvpn_service "github.com/mysteriumnetwork/node/services/openvpn" 45 "github.com/mysteriumnetwork/node/session" 46 "github.com/mysteriumnetwork/node/utils/netutil" 47 "github.com/mysteriumnetwork/node/utils/stringutil" 48 ) 49 50 // ProposalFactory prepares service proposal during runtime 51 type ProposalFactory func(currentLocation market.Location) market.ServiceProposal 52 53 // Manager represents entrypoint for Openvpn service with top level components 54 type Manager struct { 55 natService nat.NATService 56 ports port.ServicePortSupplier 57 dnsProxy *dns.Proxy 58 bus eventbus.EventBus 59 trafficFirewall firewall.IncomingTrafficFirewall 60 vpnNetwork net.IPNet 61 vpnServerPort int 62 openvpnProcess openvpn.Process 63 openvpnClients *clientMap 64 openvpnAuth *authHandler 65 ipResolver ip.Resolver 66 serviceOptions Options 67 nodeOptions node.Options 68 69 outboundIP string 70 country string 71 dnsIP net.IP 72 dnsOK bool 73 tlsPrimitives *tls.Primitives 74 } 75 76 // Serve starts service - does block 77 func (m *Manager) Serve(instance *service.Instance) (err error) { 78 m.vpnNetwork = net.IPNet{ 79 IP: net.ParseIP(m.serviceOptions.Subnet), 80 Mask: net.IPMask(net.ParseIP(m.serviceOptions.Netmask).To4()), 81 } 82 83 dnsPort := 11153 84 dnsHandler, err := dns.ResolveViaSystem() 85 if err == nil { 86 if instance.PolicyProvider().HasDNSRules() { 87 dnsHandler = dns.WhitelistAnswers(dnsHandler, m.trafficFirewall, instance.PolicyProvider()) 88 removeRule, err := m.trafficFirewall.BlockIncomingTraffic(m.vpnNetwork) 89 if err != nil { 90 return fmt.Errorf("failed to enable traffic blocking: %w", err) 91 } 92 defer func() { 93 if err := removeRule(); err != nil { 94 log.Warn().Err(err).Msg("failed to disable traffic blocking") 95 } 96 }() 97 } 98 99 m.dnsProxy = dns.NewProxy("", dnsPort, dnsHandler) 100 if err := m.dnsProxy.Run(); err != nil { 101 log.Warn().Err(err).Msg("Provider DNS will not be available") 102 } else { 103 m.dnsOK = true 104 m.dnsIP = netutil.FirstIP(m.vpnNetwork) 105 } 106 } else { 107 log.Warn().Err(err).Msg("Provider DNS will not be available") 108 } 109 110 servicePort, err := m.ports.Acquire() 111 if err != nil { 112 return fmt.Errorf("failed to acquire an unused port: %w", err) 113 } 114 m.vpnServerPort = servicePort.Num() 115 116 m.outboundIP, err = m.ipResolver.GetOutboundIP() 117 if err != nil { 118 return fmt.Errorf("could not get outbound IP: %w", err) 119 } 120 121 m.tlsPrimitives, err = primitiveFactory(m.country, instance.ProviderID.Address) 122 if err != nil { 123 return 124 } 125 126 if err := firewall.AddInboundRule(m.serviceOptions.Protocol, m.vpnServerPort); err != nil { 127 return fmt.Errorf("failed to add firewall rule: %w", err) 128 } 129 defer func() { 130 if err := firewall.RemoveInboundRule(m.serviceOptions.Protocol, m.vpnServerPort); err != nil { 131 log.Error().Err(err).Msg("Failed to delete firewall rule for OpenVPN") 132 } 133 }() 134 135 log.Info().Msgf("Starting OpenVPN server on port: %d", m.vpnServerPort) 136 if err := m.startServer(); err != nil { 137 return fmt.Errorf("failed to start Openvpn server: %w", err) 138 } 139 140 if _, err := m.natService.Setup(nat.Options{ 141 VPNNetwork: m.vpnNetwork, 142 ProviderExtIP: net.ParseIP(m.outboundIP), 143 DNSIP: m.dnsIP, 144 }); err != nil { 145 return fmt.Errorf("failed to setup NAT/firewall rules: %w", err) 146 } 147 148 s := shaper.New(m.bus) 149 err = s.Start(m.openvpnProcess.DeviceName()) 150 if err != nil { 151 log.Error().Err(err).Msg("Could not start traffic shaper") 152 } 153 defer s.Clear(m.openvpnProcess.DeviceName()) 154 155 log.Info().Msg("OpenVPN server waiting") 156 return m.openvpnProcess.Wait() 157 } 158 159 // Stop stops service 160 func (m *Manager) Stop() error { 161 if m.openvpnProcess != nil { 162 m.openvpnProcess.Stop() 163 } 164 165 if m.dnsProxy != nil { 166 if err := m.dnsProxy.Stop(); err != nil { 167 return fmt.Errorf("could not stop DNS proxy: %w", err) 168 } 169 } 170 171 return nil 172 } 173 174 // ProvideConfig takes session creation config from end consumer and provides the service configuration to the end consumer 175 func (m *Manager) ProvideConfig(sessionID string, sessionConfig json.RawMessage, conn *net.UDPConn) (*service.ConfigParams, error) { 176 if m.vpnServerPort == 0 { 177 return nil, errors.New("service port not initialized") 178 } 179 180 publicIP, err := m.ipResolver.GetPublicIP() 181 if err != nil { 182 return nil, fmt.Errorf("could not get public IP: %w", err) 183 } 184 185 serverIP := vpnServerIP(m.outboundIP, publicIP, m.nodeOptions.OptionsNetwork.Network.IsLocalnet()) 186 vpnConfig := &openvpn_service.VPNConfig{ 187 RemoteIP: serverIP, 188 RemotePort: m.vpnServerPort, 189 RemoteProtocol: m.serviceOptions.Protocol, 190 TLSPresharedKey: m.tlsPrimitives.PresharedKey.ToPEMFormat(), 191 CACertificate: m.tlsPrimitives.CertificateAuthority.ToPEMFormat(), 192 } 193 if m.dnsOK { 194 vpnConfig.DNSIPs = m.dnsIP.String() 195 } 196 197 if err := proxyOpenVPN(conn, m.vpnServerPort); err != nil { 198 return nil, fmt.Errorf("could not proxy connection to OpenVPN server: %w", err) 199 } 200 201 destroy := func() { 202 log.Info().Msgf("Cleaning up session %s", sessionID) 203 204 sessionClients := m.openvpnClients.GetSessionClients(session.ID(sessionID)) 205 for clientID := range sessionClients { 206 if err := m.openvpnAuth.ClientKill(clientID); err != nil { 207 log.Error().Err(err).Msgf("Cleaning up session %s failed. Error disconnecting Openvpn client %d", sessionID, clientID) 208 } 209 } 210 } 211 212 return &service.ConfigParams{SessionServiceConfig: vpnConfig, SessionDestroyCallback: destroy}, nil 213 } 214 215 func (m *Manager) startServer() error { 216 vpnServerConfig := NewServerConfig( 217 m.nodeOptions.Directories.Runtime, 218 m.nodeOptions.Directories.Script, 219 m.serviceOptions.Subnet, 220 m.serviceOptions.Netmask, 221 m.tlsPrimitives, 222 m.nodeOptions.BindAddress, 223 m.vpnServerPort, 224 m.serviceOptions.Protocol, 225 ) 226 227 openvpnFilterDeny := stringutil.Split(config.GetString(config.FlagFirewallProtectedNetworks), ',') 228 var openvpnFilterAllow []string 229 if m.dnsOK { 230 openvpnFilterAllow = []string{m.dnsIP.String()} 231 } 232 233 stateChannel := make(chan openvpn.State, 10) 234 m.openvpnAuth = newAuthHandler(m.openvpnClients, identity.NewExtractor()) 235 m.openvpnProcess = openvpn.CreateNewProcess( 236 m.nodeOptions.Openvpn.BinaryPath(), 237 vpnServerConfig.GenericConfig, 238 filter.NewMiddleware(openvpnFilterAllow, openvpnFilterDeny), 239 m.openvpnAuth, 240 state.NewMiddleware(func(state openvpn.State) { 241 stateChannel <- state 242 // this is the last state - close channel (according to best practices of go - channel writer controls channel) 243 if state == openvpn.ProcessExited { 244 close(stateChannel) 245 } 246 }), 247 newStatsPublisher(m.openvpnClients, m.bus, 1), 248 ) 249 if err := m.openvpnProcess.Start(); err != nil { 250 return err 251 } 252 253 // Wait for started state 254 for { 255 state, more := <-stateChannel 256 if !more { 257 return errors.New("process failed to start") 258 } 259 if state == openvpn.ConnectedState { 260 break 261 } 262 } 263 264 // Consume server states 265 go func() { 266 for state := range stateChannel { 267 switch state { 268 case openvpn.ProcessStarted: 269 log.Info().Msg("OpenVPN service booting up") 270 case openvpn.ProcessExited: 271 log.Info().Msg("OpenVPN service exited") 272 } 273 } 274 }() 275 276 log.Info().Msg("OpenVPN service started successfully") 277 return nil 278 }