Linux command for public ip address - linux

I want command to get Linux machine(amazon) external/public IP Address.
I tried hostname -I and other commands from blogs and stackoverflow like
ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'
and many more. But they all are giving me internal IP Address.
Then I found some sites which provides API for this.
Example : curl http://ipecho.net/plain; echo
But I don't want to rely on third party website service. So, is there any command line tool available to get external IP Address?

simplest of all would be to do :
curl ifconfig.me

A cleaner output
ifconfig eth0 | awk '/inet / { print $2 }' | sed 's/addr://'

You could use this script
# !/bin/bash
#
echo 'Your external IP is: '
curl -4 icanhazip.com
But that is relying on a third party albeit a reliable one.
I don't know if you can get your external IP without asking someone/somesite i.e. some third party for it, but what do I know.
you can also just run:
curl -4 icanhazip.com
This is doing the same thing as a command the -4 is to get the output in Ipv4

You can use this command to get public ip and private ip(second line is private ip; third line is public ip.)
ip addr | awk '/inet / {sub(/\/.*/, "", $2); print $2}'

I would suggest you to use the command external-ip (sudo apt-get install miniupnpc) as it (I'm almost sure) uses upnp protocol to ask the router instead of asking an external website so it should be faster, but of course the router has to have upnp enabled.

You can simply do this :
curl https://ipinfo.io/ip

It might not work on amazon because you might be using NAT or something for the server to access the rest of the world (and for you to ssh into it also). If you are unable to ssh into the ip that is listed in ifconfig then you are either in a different network or dont have ssh enabled.

This is the best I can do (only relies on my ISP):
ISP=`traceroute -M 2 -m 2 -n -q 1 8.8.8.8 | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'`
extIP=`ping -R -c 1 -t 1 -s 1 -n $ISP | grep RR | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'`
echo $extIP
Or, the functionally same thing on one line:
ISP=`traceroute -M 2 -m 2 -n -q 1 8.8.8.8 | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'` | ping -R -c 1 -t 1 -s 1 -n $ISP | grep RR | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
to save it to a temporary & hidden file add > .extIP to the end of the last line, then cat .extIP to see it.
If your ISP's address never changes (honestly i'm not sure if it would or not), then you could fetch it once, and then replace $ISP in line two with it
This has been tested on a mac with wonderful success.
the only adjustment on linux that I've found so far is the traceroute "-M" flag might need to be "-f" instead
and it relies heavily on the ping's "-R" flag, which tells it to send back the "Record Route" information, which isn't always supported by the host. But it's worth a try!
the only other way to do this without relying on any external servers is to get it from curl'ing your modem's status page... I've done this successfully with our frontier DSL modem, but it's dirty, slow, unreliable, and requires hard-coding your modem's password.
Here's the "process" for that:
curl http://[user]:[password]#[modem's LAN address]/[status.html] | grep 'WanIPAddress =' | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
That fetches the raw html, searches for any lines containing "WanIpAddress =" (change that so it's appropriate for your modem's results), and then narrows down those results to an IPv4 style address.
Hope that helps!

As others suggested, we have to rely on third party service which I don't feel safe using it. So, I have found Amazon API on this answer :
$ curl http://169.254.169.254/latest/meta-data/public-ipv4
54.232.200.77
For more details, https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-retrieval

The super-easy way is using the glances tool. you can install it on Ubuntu using:
$ sudo apt install glances
then using it with:
$ glances
and at the top of the terminal, it highlights your public IP address, and so many other information about your system (like what htop does) and network status.

For a formatted output use :-
dig TXT +short o-o.myaddr.l.google.com #ns1.google.com
it'll give you formatted output like this
"30.60.10.11"
also FYI,
dig is more faster than curl and wget

The following works as long as you have ifconfig and curl.
curl ifconfig.me

Related

Bash script to block mac adresses

I'm currently working on designing a linux server that has a bash script that runs every time someone new accesses the website that the server is hosting. What this bash script should do is extracting the new mac address of the client and add that mac address with other text in the before.rules file located in ufw directory.
To just extract the mac addresses from arp i'm using:
arp -a | grep eth1 | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'
The line of code that needs to be added in before.rules is:
-A ufw-before-input -m mac --mac-source "the extracted mac address" -j DROP
So anyone having any idea of how i could do this script?
Define a variable to contain your first command (which gives you the MAC address), then output the second line of code with that value in it.
#!/bin/bash
ufwdir='SOME/DIRECTORY'
mac=$(arp -a | grep eth1 | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}')
echo "-A ufw-before-input -m mac --mac-source \"$mac\" -j DROP" >>$UFWDIR/before.rules
Important / disclaimer:
use >> to write to the file, if you use > it will truncate the file before adding that one single line!
I have not tested this code, I simply reused your commands from your question.

Add time and IP before bash cursor on Linux server SSH

I was thinking about syntax looking like this:
IP: 123.123.123 | 28.10.2016 17:24 | root#vps:~$
Is it possible?
I wish log bash history with this data for debugging and backup.
I was try on it, but time is static and I don't know how write IP:
echo "force_color_prompt=yes" >> /root/.bashrc
echo "PS1='$(date +%T) | ${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '" >> /root/.bashrc
Maybe IP can be printed only first time after SSH login, is it possible?
Thanks
For IP getting printed out, add following lines to your .bashrc:
ip=`ip a | grep wlan0 | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1`
echo $ip
unset $ip
Now when ever you open a new terminal, your will get ip printed out for you. Same goes for ssh.
Please notice that Im using my wlan0 adapter to get the ip, you may need to change that to eth0 depending on your environment.
Set ip with Farhad's answer, then:
PS1='IP: $ip | \D{%d.%m.%G %H:%M} | \u#\h:\W$'
The time is dynamic.
References
Controlling the Prompt - Bash Reference Manual
STRFTIME(3) - Linux Programmer's Manual

Is it possible to run command "route -n" specifically for a NIC

I am fairly new to linux I wanted to ask if its possible in linux commands to run a "route -n" command to retrieve information for a specific NIC. E.G route -n ether0. Because currently it shows me for all the NIC's but what if I want just for one?
Use the iproute2 ip command (rather than the antique route command), and provide a selector with your NIC:
# for ether0
ip -o route list dev ether0
(I've added -o since your tags indicate that you're using this for scripting purposes; ensuring that each result lives on its own line is appropriate in this case).
This is a significant improvement on the simple route | grep ether0 approach, as it shows routing entries which can end up sending traffic through a NIC but don't name that NIC explicitly.
As the default for iproute2 is to avoid leaning on the resolver, no local flag equivalent to -n is necessary; instead, if you did want to use the resolver, you would need to add -r.
Do you want see route for ether0, you can use below command
ip -o route show dev ether0
or
ip route show | grep ether0
or
route -n | grep ether0
or
netstat -nr | grep ether0
To see NIC for ether0, you can use ifconfig command and Gateway NIC you can use arp -a commands
ifconfig ether0
for see GW and direct connected NICS you can use below command
arp -a

Is it a good idea to add a bash code snippet into a bash conf file that is sourced by a bash script?

I have an executable bash script that picks up my external ip address from my modem and uploads it in a dynamic DNS service. The script is accompanied by a configuration file which I source from the script. The configuration file holds values for modem credentials, FQDN for my hostname, modem ip address and "status" website address.
In order to pick up my external IP address, I need to wget the "status" webpage from my modem and do some grep and sed operations to grab the external IP.
So the actual grep and sed code is also custom for every user.
The main question is: Canonically speaking, should such code be present in the conf file or in the script itself.
I am confused because I read this in 2 ways:
it is code so it should be in the script
it is variable so it should be in the config
I know this may sound like storm in a tea cup, but I would like to learn the right way.
Also, if you believe the right way is (2), I don't know how to declare the code in the configuration file. I tried the following and doesn't work. I've also not been able to find similar examples in the internet.
config:
grab_modem_ip='grep "[0-9]*\.[0-9]*\.[0-9]*\.[[0-9]*" |
grep tabdata | sed 's/\(.*\)<\/td>.*/\1/''
or
alias grab_modem_ip='grep "[0-9]*\.[0-9]*\.[0-9]*\.[[0-9]*" |
grep tabdata | sed 's/\(.*\)<\/td>.*/\1/''
(Notice that I have wrapped the whole command in '...' — single quotes.)
script
ipaddr=$( wget --user ${modemuser} --password ${modempass} "${modemsite}" -O - 2>/dev/null | "<grab_modem_ip>" )
I think that maybe 2 the correct solution. And I think that your command will solve using this:
ipaddr=$( wget --user ${modemuser} --password ${modempass} "${modemsite}" -O - 2>/dev/null | eval "grab_modem_ip" )
The answer I was looking for was "Variables hold data. Functions hold code. Don't put code inside variables!" as quoted from Greg's Wiki
so I rewrote grab_modem_ip as a function, that is defined in the conf file.
grab_modem_ip()
{
echo "${1}" | grep "[0-9]*\.[0-9]*\.[0-9]*\.[[0-9]*" | grep tabdata | sed 's/\(.*\)<\/td>.*/\1/'
}
Then invokation in the script is done as
modemstatuspage=$( wget --user ${modemuser} --password ${modempass} "${modemsite}" -O - 2>/dev/null )
ipaddr=$( grab_modem_ip "${modemstatuspage}")

Bash Script Block All Apple Devices

I am trying to create a shell script to block all apple devices on my network. I am using nmap for os detection. What I have so far is this:
while (true) do
nmap -O -T4 -p 22,80 -v 172.20.0.0/24 | grep -B9 'OS details: Apple' | \
grep 'Nmap scan report for' | cut -f4 -d'r' | cut -f2 -d' ' | \
iptables -i wlan0 -A INPUT -j DROP -s
sleep 10
done
Is there a way to simplify this at all so there is less grepping and cutting involved?
Also, this script will run into errors if there are more than one or zero apple devices found on the network. Is it possible to add logic for that?
Yes, of course it is possible. You can use perl/awk to simplify the script a lot.
Also, I'm not sure that your script is correct at the moment.
You have a pipe that write addresses to iptables, but iptables
doesn't work this way.
If you want to run iptables for each address that is produced by nmap,
you can read the addresses using read to some variable (in my example ADDR)
and then use the variable in iptables:
while (true) do
nmap -O -T4 -p 22,80 -v 172.20.0.0/24 | grep -B9 'OS details: Apple' | \
grep 'Nmap scan report for' | cut -f4 -d'r' | cut -f2 -d' ' | \
while read ADDR
do
iptables -i wlan0 -A INPUT -j DROP -s $ADDR
done
sleep 10
done
A few more remarks:
You do not need the parenthesis around true. This starts a new subshell, which is inefficient. In this case, you probably won't care, but it's good practice to avoid needless subshells.
the $ADDR in Igor Chubin's answer is dangerous. If $ADDR contains a whitespace character, it will be split up into separate parameters. Someone on the network may be able to affect the output of NMap, and modify the structure of the iptables command. Even if this is not the case here, it's good practice to put the argument in between double quotes whenever possible to prevent this: "$ADDR".
for similar reasons, you'll usually want to use read -r instead of just read. Without the -r parameter, backslash characters in the input will escape subsequent special characters (such as spaces).
NMap has its own Lua scripting support. This is another way to go at this problem, which may prevent you from having to parse any text at all.
If you are physically on the same network, you may be able to block Apple devices without any NMap at all, by blocking devices based on the MAC address of the device. The first three bytes identify the organisation which issued the MAC address. You can look them up here. They can be faked on a rooted device, but then again, so can the NMap fingerprinting (though that would likely be harder).
An important part of scripting is understanding the programs you are using and how to get the appropriate output from them. It looks like you have a decent understanding of Nmap, since you limit the number of ports scanned (-p 22,80) and request OS detection (-O), but you could avoid a lot of text processing if you used the appropriate output format.
Nmap's "grepable" format is deprecated, meaning that it can't be used to get a lot of more-recent features' output, but it works just fine for OS detection. You request it with -oG. Here's an example, borrowing some looping help from #IgorChubin's excellent answer:
while (true) do
nmap -O -T4 -p 22,80 -oG - 172.20.0.0/24 | awk '/OS: Apple/{print $2}' | \
while read ADDR
do
iptables -i wlan0 -A INPUT -j DROP -s $ADDR
done
sleep 10
done
Some other improvements include moving the sleep 10 into the while condition of the outermost loop, to allow killing it with Ctrl-C during one of the sleeps. Also, be aware that DHCP leases expire, and the IP you are blocking may be assigned to a different system in the future. In general, this approach does not seem like the best way to accomplish what you want.

Resources