简体   繁体   English

bash中公网IP地址检测方法

[英]Methods to detect public IP address in bash

As part of an installation script, I want to make an "educated guess" about the machines public IP address.作为安装脚本的一部分,我想对机器的公共地址 IP 进行“有根据的猜测”。 It should be as robust as possible, working on a variety of hosts and platforms.它应该尽可能健壮,可以在各种主机和平台上工作。 Here is an example:这是一个例子:

https://gist.github.com/4669037 https://gist.github.com/4669037

This script uses 3 methods and then defaults to the value of /etc/hostname .此脚本使用 3 种方法,然后默认为/etc/hostname的值。 I have only tested this on Ubuntu so far.到目前为止,我只在 Ubuntu 上测试过这个。 Will this be likely to work on other distributions?这可能适用于其他发行版吗? And are there additional methods that I could add?还有我可以添加的其他方法吗?

curl ipinfo.io/ip

Or要么

wget -q -O - ipinfo.io/ip

Or要么

lynx -source ipinfo.io/ip

get public ip address获取公共IP地址

curl ifconfig.me将是最佳选择,以防您没有 curl:

wget -qO- ifconfig.me/ip

How much public public IP are you looking for?您要寻找多少公共公共 IP? What if the machine is behind NAT?如果机器在 NAT 后面怎么办?

  • curl / wget / netcat ( nc ) <URL> which contains requester's address: should work most of the time, but may the site may be unreachable from the machine (be it firewall or temporary/permanent unavailability). curl / wget / netcat ( nc ) <URL>包含请求者的地址:应该在大部分时间都可以工作,但该站点可能无法从机器访问(无论是防火墙还是临时/永久不可用)。 You'll get the most public IP you can.您将获得尽可能多的公共 IP。

  • ifconfig : must run as root, otherwise you'd have to try /sbin/ifconfig or /usr/sbin/ifconfig as well. ifconfig :必须以 root 身份运行,否则您还必须尝试/sbin/ifconfig/usr/sbin/ifconfig What if the machine has more NICs?如果机器有更多的网卡怎么办? How do you tell what IP is the right one?你如何判断哪个IP是正确的? What if only IPv6 is used on the machine's LAN?如果机器的 LAN 上只使用 IPv6 会怎样? In any case, you'll get the least public IP you can (and possibly a wrong one if more interfaces are configured on the machine - which often is the case these days with omnipresent virtualization using network tap devices and/or).在任何情况下,您都将获得尽可能少的公共 IP(如果在机器上配置了更多接口,则可能是错误的 IP——如今使用网络分流设备和/或无所不在的虚拟化通常就是这种情况)。

  • /etc/hostname : does not need to exist, on many systems it is /etc/HOSTNAME , and it does not contain IP address rather it should contain the hostname (usually the FQDN). /etc/hostname :不需要存在,在许多系统上它是/etc/HOSTNAME ,它不包含 IP 地址,而应该包含主机名(通常是 FQDN)。

The point is, that the ways in which it can fail are numerous and you probably should consider either a) specifying more precisely what systems you are targeting or b) whether you really need to know the IP at all - is a solution that seems to work in simple cases worth using when it fails miserably in slightly more complicated setup?关键是,它可能失败的方式有很多,您可能应该考虑 a) 更准确地指定您的目标系统或 b) 您是否真的需要知道 IP - 似乎是一个解决方案在简单的情况下工作,当它在稍微复杂的设置中惨遭失败时值得使用吗? If you think you need the IP, prepare a way to handle failures gracefully in cases where you either don't get the IP at all or you get a wrong one.如果您认为您需要 IP,请准备一种方法来优雅地处理故障,以防您根本没有获得 IP 或获得错误的 IP。

试试这个命令:

wget -O - -q icanhazip.com

If on an AWS EC2 you can use:如果在 AWS EC2 上,您可以使用:

curl checkip.amazonaws.com

NOTE: this service can be used from any web client.注意:此服务可从任何 Web 客户端使用。

I found my personal preferred method here:我在这里找到了我个人喜欢的方法:

  • dig +short myip.opendns.com @resolver1.opendns.com
  • dig +short txt ch whoami.cloudflare @1.0.0.1
  • dig +short txt oo.myaddr.l.google.com @ns1.google.com
    • dig +short txt oo.myaddr.l.google.com @ns1.google.com | awk -F'"' '{print $2}'

This solution doesn't work if you're behind nat or something.如果您落后于 nat 或其他东西,则此解决方案不起作用。 It helps without a 3rd party service.它在没有 3rd 方服务的情况下有所帮助。 It works if the machine has the connection on it, like a server, or a ppp connection.如果机器上有连接,如服务器或 ppp 连接,它就可以工作。

  • Not an exactly correct answer to question, but probably helps other people (like me)不是一个完全正确的问题答案,但可能会帮助其他人(比如我)
  • Requires to be root in most (or all?) cases在大多数(或所有?)情况下需要 root

You can get the (first) default route from route -n , find the interface it uses, and find the ip it has.您可以从route -n获取(第一个)默认路由,找到它使用的接口,并找到它拥有的 ip。

MAINIF=$( route -n | grep '^0\.0\.0\.0' | head -n 1 | awk '{print $NF}' )
IP=$( ifconfig $MAINIF | { IFS=' :';read r;read r r a r;echo $a; } )

Using only bash (with help from icanhazip.com ):仅使用 bash(在icanhazip.com 的帮助):

exec 3<>/dev/tcp/icanhazip.com/80 
echo -e 'GET / HTTP/1.0\r\nhost: icanhazip.com\r\n\r' >&3 
while read i
do
 [ "$i" ] && myip="$i" 
done <&3 
echo "$myip"

bash opens open a socket to icanhazip and sends an http request, the IP address is returned on the last non-empty line of the data returned. bash 打开一个到 icanhazip 的套接字并发送一个 http 请求,IP 地址在返回数据的最后一个非空行上返回。 (previous lines are http headers) (前几行是 http 标头)

This avoids the need for http client like wget or curl.这避免了像 wget 或 curl 这样的 http 客户端的需要。

使用 curl 打shtuff.it IP 服务

curl http://shtuff.it/myip/short

Use ipify API:使用ipify API:

curl 'https://api.ipify.org?format=json'

Bash script: bash脚本:

#!/bin/bash

ip=$(curl -s https://api.ipify.org)
echo "My public IP address is: $ip"

我使用 IPGrab 是因为它很容易让我记住。

curl http://ipgrab.io

I was getting whitespace characters at the end of other commands:我在其他命令的末尾得到空格字符:

$ curl -s https://api.ipify.org
255.255.255.255%

I found that using jsonip.com combined with jq got rid of this.我发现使用 jsonip.com 结合jq摆脱了这个。 This way, parsing the IP address is as easy as a jq expression:这样,解析 IP 地址就像 jq 表达式一样简单:

$ curl -s https://jsonip.com | jq -r '.ip'
255.255.255.255

See this jq play .看到这个jq 播放

Donde: remote es un host al que tengas acceso y home es un host del que quieres averiguar su ip东德:远程 es un host al que tengas acceso y home es un host del que quieres averiguar su ip

Script bash:脚本重击:

 #!/bin/bash

 host_remote="sirio.fun"
 host_home="tutia.ovh"
      
 ip_home=$(ssh $host_remote ping -c 1 $host_home | awk '/bytes from/ {print $4}')
        
 echo $ip_home

Para cron:节拍:

#!/bin/bash

function alert() {
    echo "Old ip: "$ip_home_save
    echo "New ip: "$ip_home
    
    echo "Se guarda la nueva ip"
    ssh $host_remote ping -c 1 $host_home | awk '/bytes from/ {print $4}' > $host_remote_file
}

host_remote="sirio.fun"
host_home="cacadela.vaca"

host_remote_file=/tmp/${host_remote}.tmp

ip_home=$(ssh $host_remote ping -c 1 $host_home | awk '/bytes from/ {print $4}')

if [[ -f $host_remote_file ]]; then
    ip_home_save=$(cat $host_remote_file)
    echo $ip_home
    echo $ip_home_save
    [[ $ip_home == $ip_home_save ]] || error=1
else
    echo "No existen datos para comprobar, se generan ahora para futuras referencias"
    ssh $host_remote ping -c 1 $host_home | awk '/bytes from/ {print $4}' > $host_remote_file
    exit 1
fi

[[ $error ]] && alert || echo "No problem"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM