github.com/richardwilkes/toolbox@v1.121.0/xio/network/external_ip.go (about)

     1  // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the Mozilla Public
     4  // License, version 2.0. If a copy of the MPL was not distributed with
     5  // this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  //
     7  // This Source Code Form is "Incompatible With Secondary Licenses", as
     8  // defined by the Mozilla Public License, version 2.0.
     9  
    10  package network
    11  
    12  import (
    13  	"io"
    14  	"net"
    15  	"net/http"
    16  	"strings"
    17  	"time"
    18  
    19  	"github.com/richardwilkes/toolbox/xio"
    20  )
    21  
    22  var sites = []string{
    23  	// These seem to prefer ipv4 responses, if possible
    24  	"http://whatismyip.akamai.com/",
    25  	"https://myip.dnsomatic.com/",
    26  	"http://api.ipify.org/",
    27  	"http://checkip.amazonaws.com/",
    28  
    29  	// These seem to prefer ipv6 responses, if possible
    30  	"http://icanhazip.com/",
    31  	"https://myexternalip.com/raw",
    32  	"http://ifconfig.io/ip",
    33  	"http://ident.me/",
    34  }
    35  
    36  // ExternalIP returns your IP address as seen by external sites. It does this by iterating through a list of websites
    37  // that will return your IP address as they see it. The first response with a valid IP address will be returned. timeout
    38  // sets the maximum amount of time for each attempt.
    39  func ExternalIP(timeout time.Duration) string {
    40  	client := &http.Client{Timeout: timeout}
    41  	for _, site := range sites {
    42  		if ip := externalIP(client, site); ip != "" {
    43  			return ip
    44  		}
    45  	}
    46  	return ""
    47  }
    48  
    49  func externalIP(client *http.Client, site string) string {
    50  	if resp, err := client.Get(site); err == nil { //nolint:noctx // The timeout on the client provides the same effect
    51  		defer xio.DiscardAndCloseIgnoringErrors(resp.Body)
    52  		var body []byte
    53  		if body, err = io.ReadAll(resp.Body); err == nil {
    54  			if ip := net.ParseIP(strings.TrimSpace(string(body))); ip != nil {
    55  				return ip.String()
    56  			}
    57  		}
    58  	}
    59  	return ""
    60  }