如何找到服务器的真实IP地址

huangapple go评论82阅读模式
英文:

How to find server real IP

问题

你可以使用以下方法来获取程序所在机器或服务器的公共IP地址:

  1. 使用网络请求库:你可以使用像requests这样的网络请求库来获取公共IP地址。通过向一个公共IP地址查询服务发送请求,你可以获取到你所在机器的公共IP地址。以下是一个示例代码:
import requests

def get_public_ip():
    response = requests.get('https://api.ipify.org?format=json')
    data = response.json()
    public_ip = data['ip']
    return public_ip

public_ip = get_public_ip()
print('running at', public_ip)
  1. 使用系统命令:在某些操作系统上,你可以使用系统命令来获取公共IP地址。以下是一个在Linux系统上使用curl命令获取公共IP地址的示例代码:
import subprocess

def get_public_ip():
    command = "curl -s ifconfig.me"
    process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    output, error = process.communicate()
    public_ip = output.decode('utf-8').strip()
    return public_ip

public_ip = get_public_ip()
print('running at', public_ip)

这些方法可以帮助你获取程序所在机器或服务器的公共IP地址,并将其打印出来。请根据你的需求选择适合的方法。

英文:

How do I find the public IP address of the machine or server my program is running on?

Like when the program is executed it detect the public of the server and print for e.g.running at 123.45.67.89

答案1

得分: 4

简短回答是,没有一种方法能够保证返回你的“公共”IP地址。

首先要问的是,你的公共IP地址是什么?你的机器地址,即连接到你的系统所看到的地址,可能会因你本地互联网服务的配置方式和你连接的服务而有所不同:

  • 正如我在评论中提到的,在典型的家庭环境中,你的机器并没有一个公共IP地址。公共地址由你的路由器托管。

  • 如果你通过代理或VPN访问服务,你的机器地址可能与直接连接到服务时完全不同。

  • 在具有多个接口的系统上,选择的源地址可能取决于你连接的地址:不同的地址可能有不同的路由。

你可以尝试使用类似http://icanhazip.com/的服务来确定你的公共IP。在许多情况下,这将是正确的,但并非所有情况都适用。

英文:

The short answer is that there's no method guaranteed to return your "public" ip address.


The first question is, what is your public ip address? The address of your machine, as seen by the system to which you are connecting, may vary depending on how your local Internet service is configured and on the service to which you're connecting:

  • As I mentioned in a comment, in a typical home environment your machine doesn't have a public ip address. The public address is hosted by your router.

  • If you're accessing a service through a proxy or vpn, your machine's address may be entirely different from when you're directly connecting to a service.

  • On a system with multiple interfaces, the origin address selected may depend upon the address to which you are connecting: different addresses may have different routes.

You can try using a service like http://icanhazip.com/ to try to determine your public ip. This will be correct in many but not all situations.

答案2

得分: 2

公共IP地址是一个模糊的概念,在实践中,它可能是静态地址,也可能不是。关于这个问题,你想知道什么?它只是一个在一定时间内有效的终端点,这取决于许多因素,比如用于发出查询的接口。

我们可以使用主线BitTorrent DHT来给我们一些指示。

Go语言提供了由anacrolix编写的很酷的dht包

当用find_peers命令查询节点时,我们会收到一个包,其中包含对等方与我们的查询关联的远程IP地址。这在bep10中有描述。

如果UDP连接不是一个好的选择,你可以选择bittorent trackers的查询,如bep24中所述。

请注意,对等方可能是恶意的,因此结果越多越好。

下面的程序输出与发起查询的计算机相关联的外部网络地址列表,从查询的节点队列的角度来看。

地址按响应的数量进行评分。

还可以阅读https://www.bittorrent.org/beps/bep_0005.html

找到9个引导节点
找到6个对等方
4    [2001:861:51c5:xxx:40d1:8061:1fe0:xxx]:9090
2    81.96.42.191:9090
  • 4个对等方告诉我们我们正在使用[2001:861:51c5:xxx:40d1:8061:1fe0:xxx]:9090,我们可以推断这是IPv6。
  • 其中2个告诉我们我们正在使用81.96.42.191:9090,这是IPv4接口。
package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"sort"
	"sync"
	"time"

	"github.com/anacrolix/dht"
	"github.com/anacrolix/dht/krpc"
	"github.com/anacrolix/torrent/bencode"
)

var maxTimeout = time.Second * 5

func main() {
	b, _ := ioutil.ReadFile("db.json")
	var rawAddrs []string
	json.Unmarshal(b, &rawAddrs)
	defer func() {
		if len(rawAddrs) < 1 {
			return
		}
		if len(rawAddrs) > 30 {
			rawAddrs = rawAddrs[:30]
		}
		buf, err := json.Marshal(rawAddrs)
		if err != nil {
			panic(err)
		}
		err = ioutil.WriteFile("db.json", buf, os.ModePerm)
		if err != nil {
			panic(err)
		}
		fmt.Fprintf(os.Stderr, "%v peers recorded\n", len(rawAddrs))
	}()
	bootstrap, err := parseAddrs(rawAddrs)
	if err != nil {
		bootstrap, err = globalBootstrapAddrs()
		if err != nil {
			panic(err)
		}
	}

	findPeers := []byte(`d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe`)

	local, err := net.ResolveUDPAddr("udp", "0.0.0.0:9090")
	if err != nil {
		panic(err)
	}
	ln, err := net.ListenUDP("udp", local)
	if err != nil {
		panic(err)
	}

	addrscores := map[string]int{}

	var drain drain
	defer drain.Wait()
	fmt.Fprintf(os.Stderr, "found %v bootstrap peers\n", len(bootstrap))
	res, errs := readResponses(ln, len(bootstrap), sendQuery(ln, bootstrap, findPeers))
	drain.Errors(errs)

	peers := []net.Addr{}
	for d := range res {
		if isValidAddr(d.IP.UDP()) {
			addrscores[d.IP.String()]++
			d.R.ForAllNodes(func(arg1 krpc.NodeInfo) {
				peers = append(peers, arg1.Addr.UDP())
			})
		}
	}

	if len(peers) > 0 {
		fmt.Fprintf(os.Stderr, "found %v peers\n", len(peers))
		res, errs = readResponses(ln, len(peers), sendQuery(ln, peers, findPeers))
		drain.Errors(errs)
		for d := range res {
			if isValidAddr(d.IP.UDP()) {
				addrscores[d.IP.String()]++
			}
		}
	}

	for _, peer := range peers {
		if isValidAddr(peer) {
			rawAddrs = append(rawAddrs, peer.String())
		}
	}

	addrs := make([]string, 0, len(addrscores))
	for addr := range addrscores {
		addrs = append(addrs, addr)
	}
	sort.Slice(addrs, func(i int, j int) bool {
		return addrscores[addrs[i]] > addrscores[addrs[j]]
	})

	for _, addr := range addrs {
		fmt.Printf("%-4v %v\n", addrscores[addr], addr)
	}
}

type drain struct{ sync.WaitGroup }

func (d *drain) Errors(errs <-chan error) {
	d.Add(1)
	go func() {
		defer d.Done()
		for err := range errs {
			fmt.Fprintln(os.Stderr, err)
		}
	}()
}

func parseAddrs(rawAddrs []string) (addrs []net.Addr, err error) {
	for _, s := range rawAddrs {
		host, port, err := net.SplitHostPort(s)
		if err != nil {
			panic(err)
		}
		ua, err := net.ResolveUDPAddr("udp", net.JoinHostPort(host, port))
		if err != nil {
			log.Printf("error resolving %q: %v", host, err)
			continue
		}
		addrs = append(addrs, ua)
	}
	if len(addrs) == 0 {
		err = errors.New("nothing resolved")
	}
	return
}

func globalBootstrapAddrs() (addrs []net.Addr, err error) {
	bootstrap, err := dht.GlobalBootstrapAddrs("udp")
	if err != nil {
		return nil, err
	}
	for _, b := range bootstrap {
		addrs = append(addrs, b.Raw())
	}
	return
}

func isValidAddr(addr net.Addr) bool { // so weird guys.
	return addr.String() != "<nil>" && addr.String() != ":0"
}

func sendQuery(ln *net.UDPConn, peers []net.Addr, query []byte) chan error {
	errs := make(chan error)

	for _, addr := range peers {
		go func(addr net.Addr) {
			_, err := ln.WriteTo(query, addr)
			if err != nil {
				errs <- addressedError{Op: "send", error: err, Addr: addr}
			}
		}(addr)
	}

	return errs
}

func readResponses(ln *net.UDPConn, count int, errs chan error) (<-chan krpc.Msg, <-chan error) {

	data := make(chan krpc.Msg)
	var wg sync.WaitGroup
	for i := 0; i < count; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			buf := make([]byte, 1000)
			ln.SetReadDeadline(time.Now().Add(maxTimeout))
			n, remoteAddr, err := ln.ReadFromUDP(buf)
			if err != nil {
				errs <- addressedError{Op: "rcv", error: err, Addr: remoteAddr}
				return
			}
			var m krpc.Msg
			err = bencode.Unmarshal(buf[:n], &m)
			if err != nil {
				errs <- addressedError{Op: "rcv", error: err, Addr: remoteAddr}
				return
			}
			data <- m
		}()
	}
	go func() {
		wg.Wait()
		close(errs)
		close(data)
	}()

	return data, errs
}

type addressedError struct {
	error
	Op   string
	Addr net.Addr
}

func (a addressedError) Error() string {
	if !isValidAddr(a.Addr) {
		return fmt.Sprintf("%-5v %v", a.Op, a.error.Error())
	}
	return fmt.Sprintf("%-5v %v: %v", a.Op, a.Addr.String(), a.error.Error())
}
英文:

public IP address is a vague notion, in practice, it might or might not be a static address. What do you know about that ? It is just a endpoint valid for a certain amount of time, which depends on many factors like which interface was used to issue the query.

We can use the mainline bittorrent dht to give us some indications.

The Go language provides the cool dht package written by anacrolix.

When querying nodes with a find_peers verb we receive a packet containing the remote ip address the peer has associated with our query. This is described in bep10.

If an UDP connection is not a good option, you might opt for a query to bittorent trackers as described in bep24

Consider that peers might be malicious, thus the more results, the better.

Below program outputs the list of external network addresses associated with the computer initiating the query from the POV of the cohort of nodes queried.

Addresses are scored by the numbers of response.

read also https://www.bittorrent.org/beps/bep_0005.html

found 9 bootstrap peers
found 6 peers
4    [2001:861:51c5:xxx:40d1:8061:1fe0:xxx]:9090
2    81.96.42.191:9090
  • 4 peers told us that we were using [2001:861:51c5:xxx:40d1:8061:1fe0:xxx]:9090, we can infer this is ipv6.
  • 2 of them told we were using 81.96.42.191:9090, the ipv4 interface.
package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"sort"
	"sync"
	"time"

	"github.com/anacrolix/dht"
	"github.com/anacrolix/dht/krpc"
	"github.com/anacrolix/torrent/bencode"
)

var maxTimeout = time.Second * 5

func main() {
	b, _ := ioutil.ReadFile("db.json")
	var rawAddrs []string
	json.Unmarshal(b, &rawAddrs)
	defer func() {
		if len(rawAddrs) < 1 {
			return
		}
		if len(rawAddrs) > 30 {
			rawAddrs = rawAddrs[:30]
		}
		buf, err := json.Marshal(rawAddrs)
		if err != nil {
			panic(err)
		}
		err = ioutil.WriteFile("db.json", buf, os.ModePerm)
		if err != nil {
			panic(err)
		}
		fmt.Fprintf(os.Stderr, "%v peers recorded\n", len(rawAddrs))
	}()
	bootstrap, err := parseAddrs(rawAddrs)
	if err != nil {
		bootstrap, err = globalBootstrapAddrs()
		if err != nil {
			panic(err)
		}
	}

	findPeers := []byte(`d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe`)

	local, err := net.ResolveUDPAddr("udp", "0.0.0.0:9090")
	if err != nil {
		panic(err)
	}
	ln, err := net.ListenUDP("udp", local)
	if err != nil {
		panic(err)
	}

	addrscores := map[string]int{}

	var drain drain
	defer drain.Wait()
	fmt.Fprintf(os.Stderr, "found %v bootstrap peers\n", len(bootstrap))
	res, errs := readResponses(ln, len(bootstrap), sendQuery(ln, bootstrap, findPeers))
	drain.Errors(errs)

	peers := []net.Addr{}
	for d := range res {
		if isValidAddr(d.IP.UDP()) {
			addrscores[d.IP.String()]++
			d.R.ForAllNodes(func(arg1 krpc.NodeInfo) {
				peers = append(peers, arg1.Addr.UDP())
			})
		}
	}

	if len(peers) > 0 {
		fmt.Fprintf(os.Stderr, "found %v peers\n", len(peers))
		res, errs = readResponses(ln, len(peers), sendQuery(ln, peers, findPeers))
		drain.Errors(errs)
		for d := range res {
			if isValidAddr(d.IP.UDP()) {
				addrscores[d.IP.String()]++
			}
		}
	}

	for _, peer := range peers {
		if isValidAddr(peer) {
			rawAddrs = append(rawAddrs, peer.String())
		}
	}

	addrs := make([]string, 0, len(addrscores))
	for addr := range addrscores {
		addrs = append(addrs, addr)
	}
	sort.Slice(addrs, func(i int, j int) bool {
		return addrscores[addrs[i]] > addrscores[addrs[j]]
	})

	for _, addr := range addrs {
		fmt.Printf("%-4v %v\n", addrscores[addr], addr)
	}
}

type drain struct{ sync.WaitGroup }

func (d *drain) Errors(errs <-chan error) {
	d.Add(1)
	go func() {
		defer d.Done()
		for err := range errs {
			fmt.Fprintln(os.Stderr, err)
		}
	}()
}

func parseAddrs(rawAddrs []string) (addrs []net.Addr, err error) {
	for _, s := range rawAddrs {
		host, port, err := net.SplitHostPort(s)
		if err != nil {
			panic(err)
		}
		ua, err := net.ResolveUDPAddr("udp", net.JoinHostPort(host, port))
		if err != nil {
			log.Printf("error resolving %q: %v", host, err)
			continue
		}
		addrs = append(addrs, ua)
	}
	if len(addrs) == 0 {
		err = errors.New("nothing resolved")
	}
	return
}

func globalBootstrapAddrs() (addrs []net.Addr, err error) {
	bootstrap, err := dht.GlobalBootstrapAddrs("udp")
	if err != nil {
		return nil, err
	}
	for _, b := range bootstrap {
		addrs = append(addrs, b.Raw())
	}
	return
}

func isValidAddr(addr net.Addr) bool { // so weird guys.
	return addr.String() != "<nil>" && addr.String() != ":0"
}

func sendQuery(ln *net.UDPConn, peers []net.Addr, query []byte) chan error {
	errs := make(chan error)

	for _, addr := range peers {
		go func(addr net.Addr) {
			_, err := ln.WriteTo(query, addr)
			if err != nil {
				errs <- addressedError{Op: "send", error: err, Addr: addr}
			}
		}(addr)
	}

	return errs
}

func readResponses(ln *net.UDPConn, count int, errs chan error) (<-chan krpc.Msg, <-chan error) {

	data := make(chan krpc.Msg)
	var wg sync.WaitGroup
	for i := 0; i < count; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			buf := make([]byte, 1000)
			ln.SetReadDeadline(time.Now().Add(maxTimeout))
			n, remoteAddr, err := ln.ReadFromUDP(buf)
			if err != nil {
				errs <- addressedError{Op: "rcv", error: err, Addr: remoteAddr}
				return
			}
			var m krpc.Msg
			err = bencode.Unmarshal(buf[:n], &m)
			if err != nil {
				errs <- addressedError{Op: "rcv", error: err, Addr: remoteAddr}
				return
			}
			data <- m
		}()
	}
	go func() {
		wg.Wait()
		close(errs)
		close(data)
	}()

	return data, errs
}

type addressedError struct {
	error
	Op   string
	Addr net.Addr
}

func (a addressedError) Error() string {
	if !isValidAddr(a.Addr) {
		return fmt.Sprintf("%-5v %v", a.Op, a.error.Error())
	}
	return fmt.Sprintf("%-5v %v: %v", a.Op, a.Addr.String(), a.error.Error())
}

huangapple
  • 本文由 发表于 2021年8月14日 03:30:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/68777527.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定