LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Red Hat (http://www.linuxquestions.org/questions/red-hat-31/)
-   -   [HELP] Creating a script to record IP of a website (http://www.linuxquestions.org/questions/red-hat-31/%5Bhelp%5D-creating-a-script-to-record-ip-of-a-website-800918/)

reneg4d3 04-08-2010 10:03 PM

[HELP] Creating a script to record IP of a website
 
Hello all, this is my first post here at LinuxQuestions and to start it off I have a question that may be simple. I will provide as much information that I can to help explain what it is I am trying to accomplish.
Information:
My server is running CentOS latest version
I am booting to GRSEC

My problem is that my phone's IP address changes every 10-30 minutes, and my server is IP whitelisted. So in order for me to login to my server I need to somehow record my Phones IP address into the "/etc/hosts.allow file".

Getting the IP of my phone is simple, for this I set up an account at dyndns.org. My phone successfully updates it's ip to the site whenever it changes. For this example I will use "linuxquestions.dyndns.org" In order to get my phones IP I will run a "nslookup" on linuxquestions.dyndns.org every 10 minutes.

For this I will set a cron job to run every 10 minutes.
Code:

0,10,30,45 * * * * /scripts/dyndnslinuxquestions
Now all I need to do is write the script. This is where I am having some trouble. I know that I will somehow have to grep the IP from the nslookup command and manipulate the string.

My nslookup command looks as follows:
Code:

root@LinuxQuestions [/]# nslookup linuxquestions.dyndns.org
Server:        66.45.228.250
Address:        66.45.228.250#53

Non-authoritative answer:
Name:  linuxquestions.dyndns.org
Address: 12.34.56.78

Somehow I need to grab the "12.34.56.78" IP address and write it to the "/etc/hosts.allow" file and remove the last IP written in the file.

So lets say my hosts.allow file looks like such:
Code:

# hosts.allow  This file describes the names of the hosts which are
#              allowed to use the local INET services, as decided
#              by the '/usr/sbin/tcpd' server.
#
#User 1
SSHD : 11.22.33.44/255.248.0.0 : ALLOW
# My Home IP
SSHD : 12.23.34.45 : ALLOW
# My Phone
SSHD : 13.24.35.46 : ALLOW

I need to delete the "SSHD : 13.24.35.46 : ALLOW" line every time the IP updates and then add the new IP that I gathered by using string manipulation on the "nslookup" command.

If someone could step me through the process and explain to me what each part of the script does instead of just handing it to me that would be awesome. I am here to learn not just copy and paste.

Any help would be greatly appreciated!
-Reneg4d3

bakdong 04-09-2010 12:05 AM

Code:

#!/bin/bash

usage() {
        echo Usage:
        echo -----
        echo "$(basename $0) ip/address name"
}


if [ $# != 2 ]
then
        usage
        exit
fi


ip=$(dig +short $1 );
res=$?;
if [ -f /tmp/$1.record ]; then oldip=$(cat /tmp/$1.record); else oldip="0.0.0.0";fi
if [ $res = 0 -a "$ip" !=  "$oldip" -a "$ip" != "" ] ;
then
        echo "$(date) $2 IP Changed from $oldip to $ip" | tee -a /var/log/dynipcheck.log;
        echo $ip > /tmp/$1.record ;
fi

This doesn't do exactly what you want, but might give you some pointers. You might consider using sed to change the necessary line in hosts.allow.

I might also consider using iptables instead of hosts.allow, but I suspect that's just personal preference more than any real security advantage. Other opinions might differ.

kainosnous 04-09-2010 12:59 AM

Were you looking for something like this:

Code:

#!/bin/sh

# Grep finds the Server line and sed uses a regular expression
# to cut out the IP address
NewIP=$(nslookup linuxquestions.dyndns.org | grep Server | sed -e "s/[^0-9]*\([0-9.]*\).*/\1/")

# The same happens here to get the old IP address. First I find
# the User 1 listing and following line. This isn't very pretty
OldIP=$(cat /etc/hosts.allow | grep "User 1" -A 1 | grep ALLOW | sed -e "s/[^0-9]*\([0-9.]*\).*/\1/")

echo "Changing $OldIP to $NewIP."

# Once we know the new and old IP addresses, we can use sed to
# replace them in a file. Actually, run this on any files
# that you want to replace the old with the new
sed -i "s@$OldIP@$NewIP@" /etc/hosts.allow

This isn't very elegant, but I think it does what you are looking for. Let me know how it works.

catkin 04-09-2010 01:04 AM

If you (your script) knows the old IP address then this one liner should work
Code:

sed -i "s/${old_IP//./\\.}/$(dig +short linuxquestions.org)/" hosts
Note: ${old_IP//./\\.} is bash parameter expansion, taking the value of $old_IP and globally changing every "." to "\." to make the "." stand for itself rather than "any character" in the sed substitution.

Test without the -i option!

Here it is demonstrated at the command line
Code:

c@CW8:/tmp$ cat hosts
# hosts.allow  This file describes the names of the hosts which are
#              allowed to use the local INET services, as decided
#              by the /usr/sbin/tcpd server.
#
#User 1
SSHD : 11.22.33.44/255.248.0.0 : ALLOW
# My Home IP
SSHD : 12.23.34.45 : ALLOW
# My Phone
SSHD : 13.24.35.46 : ALLOW
c@CW8:/tmp$ old_IP=13.24.35.46
c@CW8:/tmp$ sed "s/${old_IP//./\\.}/$(dig +short linuxquestions.org)/" hosts
# hosts.allow  This file describes the names of the hosts which are
#              allowed to use the local INET services, as decided
#              by the /usr/sbin/tcpd server.
#
#User 1
SSHD : 11.22.33.44/255.248.0.0 : ALLOW
# My Home IP
SSHD : 12.23.34.45 : ALLOW
# My Phone
SSHD : 75.126.162.205 : ALLOW


reneg4d3 04-09-2010 03:05 PM

Quote:

Originally Posted by bakdong (Post 3929456)
Code:

#!/bin/bash

usage() {
        echo Usage:
        echo -----
        echo "$(basename $0) ip/address name"
}


if [ $# != 2 ]
then
        usage
        exit
fi


ip=$(dig +short $1 );
res=$?;
if [ -f /tmp/$1.record ]; then oldip=$(cat /tmp/$1.record); else oldip="0.0.0.0";fi
if [ $res = 0 -a "$ip" !=  "$oldip" -a "$ip" != "" ] ;
then
        echo "$(date) $2 IP Changed from $oldip to $ip" | tee -a /var/log/dynipcheck.log;
        echo $ip > /tmp/$1.record ;
fi

This doesn't do exactly what you want, but might give you some pointers. You might consider using sed to change the necessary line in hosts.allow.

I might also consider using iptables instead of hosts.allow, but I suspect that's just personal preference more than any real security advantage. Other opinions might differ.

Thanks for the response! Thanks for the tip on using sed I will research it somemore.

Quote:

Originally Posted by kainosnous (Post 3929489)
Were you looking for something like this:

Code:

#!/bin/sh

# Grep finds the Server line and sed uses a regular expression
# to cut out the IP address
NewIP=$(nslookup linuxquestions.dyndns.org | grep Server | sed -e "s/[^0-9]*\([0-9.]*\).*/\1/")

# The same happens here to get the old IP address. First I find
# the User 1 listing and following line. This isn't very pretty
OldIP=$(cat /etc/hosts.allow | grep "User 1" -A 1 | grep ALLOW | sed -e "s/[^0-9]*\([0-9.]*\).*/\1/")

echo "Changing $OldIP to $NewIP."

# Once we know the new and old IP addresses, we can use sed to
# replace them in a file. Actually, run this on any files
# that you want to replace the old with the new
sed -i "s@$OldIP@$NewIP@" /etc/hosts.allow

This isn't very elegant, but I think it does what you are looking for. Let me know how it works.

This appears to be exactly what I want but one thing. Since I am looking for the IP of second "Address:" not the first I will have to change the script a little . it would seem you are copying the text after the first "Server:" line which in this case is "66.45.228.250".
Just from reading a little bit about sed and looking at your examples I came up with this:
Code:

NewIP=$(nslookup linuxquestions.dyndns.org | grep "dyndns.org" -A 1 | grep "Address:" | sed -e "s/[^0-9]*\([0-9.]*\).*/\1/")
When I tested that, it successfully printed out JUST my phones IP.
Also, I see your looking up "User 1" IP. I believe I would need to change that to "My Phone"
Over all this is pretty much EXACTLY what I was wanting and I learned quite a bit.
I may extend this script to be more active and do more but for the time being I believe this will work. Thanks!

Quote:

Originally Posted by catkin (Post 3929495)
If you (your script) knows the old IP address then this one liner should work
Code:

sed -i "s/${old_IP//./\\.}/$(dig +short linuxquestions.org)/" hosts
Note: ${old_IP//./\\.} is bash parameter expansion, taking the value of $old_IP and globally changing every "." to "\." to make the "." stand for itself rather than "any character" in the sed substitution.

Test without the -i option!

Here it is demonstrated at the command line
Code:

c@CW8:/tmp$ cat hosts
# hosts.allow  This file describes the names of the hosts which are
#              allowed to use the local INET services, as decided
#              by the /usr/sbin/tcpd server.
#
#User 1
SSHD : 11.22.33.44/255.248.0.0 : ALLOW
# My Home IP
SSHD : 12.23.34.45 : ALLOW
# My Phone
SSHD : 13.24.35.46 : ALLOW
c@CW8:/tmp$ old_IP=13.24.35.46
c@CW8:/tmp$ sed "s/${old_IP//./\\.}/$(dig +short linuxquestions.org)/" hosts
# hosts.allow  This file describes the names of the hosts which are
#              allowed to use the local INET services, as decided
#              by the /usr/sbin/tcpd server.
#
#User 1
SSHD : 11.22.33.44/255.248.0.0 : ALLOW
# My Home IP
SSHD : 12.23.34.45 : ALLOW
# My Phone
SSHD : 75.126.162.205 : ALLOW


Not sure I quite understand what your doing here. Care to explain a bit?

--

I think my overall script would be something like:
Code:

#!/bin/sh

# Grep finds the Server line and sed uses a regular expression
# to cut out the IP address
NewIP=$(nslookup linuxquestions.dyndns.org | grep "dyndns.org" -A 1 | grep "Address:" | sed -e "s/[^0-9]*\([0-9.]*\).*/\1/")

# The same happens here to get the old IP address. First I find
# the User 1 listing and following line. This isn't very pretty
OldIP=$(cat /etc/hosts.allow | grep "My Phone" -A 1 | grep ALLOW | sed -e "s/[^0-9]*\([0-9.]*\).*/\1/")

echo "Changing $OldIP to $NewIP."

# Once we know the new and old IP addresses, we can use sed to
# replace them in a file. Actually, run this on any files
# that you want to replace the old with the new
sed -i "s@$OldIP@$NewIP@" /etc/hosts.allow

Tested and here is results:
Code:

root@LinuxQuestions [/]# sh /scripts/android_nslookup
Changing 12.34.56.78 to 97.41.50.57.
root@LinuxQuestions [/]#

Now I venture into the file and I see:
Code:

# My Phone
SSHD : 97.41.50.57 : ALLOW

Success!

bakdong 04-09-2010 10:16 PM

You might also like to think about checking to see if the IP has changed before you actually do the substitution.

catkin 04-10-2010 01:06 AM

Quote:

Originally Posted by reneg4d3 (Post 3930261)
Not sure I quite understand what your doing here. Care to explain a bit?

dig +short linuxquestions.org returns simply the IP address so saves having to parse the response as must be done using nslookup
Code:

c@CW8:~$ dig +short linuxquestions.org
75.126.162.205

Bash substitutes the output (stdout) of command in place of $(command).

sed you know about. Its substitute command (s/<regular expression>/<replacement string>/) searches for a regular expression and replaces it with <replacement string>. In a regular expression, "." means any single character. Thus if you use an IP address as a regular expression, 192.168.1.1 will match 192.168.1.1 but it will also match 192a168Bm1z1. The special meaning of "." in a regular expression may be removed by "escaping" it with a backslash "\" thus regular expression 192\.168\.1\.1 will match only 192.168.1.1.

sed's -i option makes sed change a file "in place" -- it modifies the input file.

It is a very useful technique to try commands and parts of commands at the command line. You could have tried
Code:

dig +short linuxquestions.org
echo $(dig +short linuxquestions.org)
old_IP=13.24.35.46
echo ${old_IP//./\\.}
sed "s/${old_IP//./\\.}/$(dig +short linuxquestions.org)/" /etc/hosts.allow


catkin 04-10-2010 01:07 AM

Quote:

Originally Posted by bakdong (Post 3930577)
You might also like to think about checking to see if the IP has changed before you actually do the substitution.

If you "replace" it with an identical value then no harm is done and the program can be simpler.

DrLove73 04-10-2010 02:49 AM

Using safer code is recommended. Also, if you write to file, you are changing it's time stamp even when there is no change.

This code could and probably will be used by others also, maybe for larger number of IP's, so I would add write suppression just in case. Also, I would ADD BACKUP of hosts.allow, maybe even with time stamp in name (it does not have to be in /etc folder) so if you brake the file your system is not rendered totally useless while you re-create it by hand. If you create backup file, but without a stamp in filename, next run will overwrite the backup.

Adding smart code to view (less) backuped files from script, and option to revert to last good one would be my choice. Write once, saves you until the end of time. :-)

bakdong 04-10-2010 05:50 AM

Quote:

Originally Posted by catkin (Post 3930662)
If you "replace" it with an identical value then no harm is done and the program can be simpler.

True, but:

the principle applies regardless of the application, why do more work than is necessary and risk something going wrong?

if you test first you can avoid the possibility of replacing the value with a dud one.

What if, for instance, the lookup fails and gives an unexpected result?

catkin 04-10-2010 06:12 AM

Quote:

Originally Posted by bakdong (Post 3930800)
True, but:

the principle applies regardless of the application, why do more work than is necessary and risk something going wrong?

if you test first you can avoid the possibility of replacing the value with a dud one.

What if, for instance, the lookup fails and gives an unexpected result?

All good points :) the most salient of which is to sanity check the IP address discovered by name resolution.

bakdong 04-10-2010 06:18 AM

All learnt from bitter experience! :)


All times are GMT -5. The time now is 11:16 AM.