github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/router/allow.go (about)

     1  /*
     2   * Copyright (C) 2021 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 router
    19  
    20  import (
    21  	"net"
    22  	"net/url"
    23  	"sync"
    24  	"time"
    25  
    26  	"github.com/rs/zerolog/log"
    27  	"golang.org/x/net/context"
    28  
    29  	"github.com/mysteriumnetwork/node/requests/resolver"
    30  )
    31  
    32  var (
    33  	// DefaultRouter contains a default router used for managing routing tables.
    34  	DefaultRouter Manager
    35  	once          sync.Once
    36  )
    37  
    38  // Manager describes a routing tables management service.
    39  type Manager interface {
    40  	ExcludeIP(net.IP) error
    41  	RemoveExcludedIP(net.IP) error
    42  	Clean() error
    43  }
    44  
    45  func ensureRouterStarted() {
    46  	once.Do(func() {
    47  		if DefaultRouter == nil {
    48  			DefaultRouter = NewManager()
    49  		}
    50  	})
    51  }
    52  
    53  // ExcludeURL adds exception to route traffic directly for specified URL (host part is usually taken).
    54  func ExcludeURL(urls ...string) error {
    55  	ensureRouterStarted()
    56  
    57  	for _, u := range urls {
    58  		parsed, err := url.Parse(u)
    59  		if err != nil {
    60  			log.Error().Err(err).Msgf("Failed to parse URL: %s", u)
    61  			continue
    62  		}
    63  
    64  		addresses := resolver.FetchDNSFromCache(parsed.Hostname())
    65  		if len(addresses) == 0 {
    66  			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    67  			defer cancel()
    68  
    69  			addresses, err = net.DefaultResolver.LookupHost(ctx, parsed.Hostname())
    70  			if err != nil {
    71  				log.Error().Err(err).Msgf("Failed to exclude URL from routes: %s", parsed.Hostname())
    72  				continue
    73  			}
    74  		}
    75  
    76  		for _, a := range addresses {
    77  			ipv4 := net.ParseIP(a)
    78  			err := DefaultRouter.ExcludeIP(ipv4)
    79  			log.Info().Err(err).Msgf("Excluding URL address from the routes: %s -> %s", u, ipv4)
    80  		}
    81  	}
    82  
    83  	return nil
    84  }
    85  
    86  // RemoveExcludedURL removes exception to route traffic directly for specified URL (host part is usually taken).
    87  func RemoveExcludedURL(urls ...string) error {
    88  	ensureRouterStarted()
    89  
    90  	for _, u := range urls {
    91  		parsed, err := url.Parse(u)
    92  		if err != nil {
    93  			log.Error().Err(err).Msgf("Failed to parse URL: %s", u)
    94  			continue
    95  		}
    96  
    97  		addresses := resolver.FetchDNSFromCache(parsed.Hostname())
    98  		if len(addresses) == 0 {
    99  			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   100  			defer cancel()
   101  
   102  			addresses, err = net.DefaultResolver.LookupHost(ctx, parsed.Hostname())
   103  			if err != nil {
   104  				log.Error().Err(err).Msgf("Failed to exclude URL from routes: %s", parsed.Hostname())
   105  				continue
   106  			}
   107  		}
   108  
   109  		for _, a := range addresses {
   110  			ipv4 := net.ParseIP(a)
   111  			err := DefaultRouter.RemoveExcludedIP(ipv4)
   112  			log.Info().Err(err).Msgf("Excluding URL address from the routes: %s -> %s", u, ipv4)
   113  		}
   114  	}
   115  
   116  	return nil
   117  }
   118  
   119  // ExcludeIP adds IP based exception to route traffic directly.
   120  func ExcludeIP(ip net.IP) error {
   121  	ensureRouterStarted()
   122  
   123  	err := DefaultRouter.ExcludeIP(ip)
   124  	if err != nil {
   125  		log.Info().Err(err).Msgf("Excluding IP address from the routes: %s", ip)
   126  	}
   127  
   128  	return nil
   129  }
   130  
   131  // Clean removes all previously added routing rules.
   132  func Clean() error {
   133  	ensureRouterStarted()
   134  
   135  	err := DefaultRouter.Clean()
   136  	if err != nil {
   137  		log.Info().Err(err).Msgf("Failed to clean")
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  // RemoveExcludedIP removes IP based exception to route traffic directly.
   144  func RemoveExcludedIP(ip net.IP) error {
   145  	ensureRouterStarted()
   146  
   147  	err := DefaultRouter.RemoveExcludedIP(ip)
   148  	if err != nil {
   149  		log.Info().Err(err).Msgf("Removing excluded IP address from the routes: %s", ip)
   150  	}
   151  
   152  	return nil
   153  }