View Single Post
Old 24th November 2008
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 4,125
Default

This is what I have now. Not completely as I want it, but didn't want to have you wait any longer

This is the sample virtual hosts configuration file I used:
Code:
$cat virt_orig.txt           
# start of virtual hosts
<VirtualHost 11.11.11.11:80>
    ServerName kpn.com
    ServerAlias www.kpn.com
</VirtualHost>

# a remark preceded by an empty line
<VirtualHost 22.22.22.22:80>
    # ServerName fish.org 
    ServerName gorilla.org
    ServerAlias www.gorilla.org
</VirtualHost>
# another remark followed by an empty line

<VirtualHost 33.33.33.33:8080>
    # --- home of the monkeys
    ServerName monkey.org
    ServerAlias www.monkey.org
    ServerAdmin webmaster@monkey.org
</VirtualHost>

<VirtualHost 4.4.4.4:8080>
    #
    # Our forum
    # 
    ServerName daemonforums.org
    ServerAlias www.daemonforum.org
    ServerAdmin webmaster@monkey.org
</VirtualHost>
You first run the dig-them script (see my previous posts) to extract the servernames and lookup the corresponding IP address
Code:
$ ./dig-them virt_orig.txt                
kpn.com=145.7.192.133
gorilla.org=128.121.215.221
monkey.org=152.160.49.201
daemonforums.org=67.205.67.40
This produces the current domain -> IP address mappings.

The perl script, I called it 'virt-update', will read a file called 'domain-addr.txt' and expects this format. To create this file
Code:
$ ./dig-them virt_orig.txt >domain-addr.txt
The name 'domain-addr.txt' is still hard-coded in the 'virt-update' perl script, but that could be changed

Now you can run the following perl script:
Code:
#!/usr/bin/perl -w

# $Id: virt-update,v 1.4 2008/11/24 01:47:17 j65nko Exp $ 

#  Copyright (c) 2008 J65nko <Administrator daemonforums.org>
# 
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
# 
#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# 

use strict ;

my @section ;  # <VirtualHost> ... </VirtualHost> section
my %address ;  # hash with  domain -> IP mappings 
my $debug ;

sub parse ;
sub process_section ;
sub show ;
sub get_ServerName ;
sub write_section ;
sub write_rejects ;

sub parse {
    my $i = -1 ; # first element of array is array[0], and we use ++$i
    while (<>) {
    	if ( /^\s*<VirtualHost/ .. /^\s*<\/VirtualHost>/ ) {
	    $section[++$i] = $_ ; # store line in array @section
	    #print  "Storing: $_" ;
            if ( /^\s*<\/VirtualHost>/ ) { # complete section stored? 
            	process_section ; 
	        $#section = 0 ; # empty @section array 
		$i = -1 ;       # init index	
            }
	next ;
	}
	#print   "\nPassing through unprocessed: $_" ;
	print RESULT ; # simply pass through non-section lines 
    } # end while
} # end sub

sub process_section {
    my $domain ;
    my $ip ;
    my $port ; 
    
    $domain = get_ServerName ; # scan @section for Servername
    if ( $domain eq "" ) { die 'Panic: No ServerName directive' ; }
    # we didn't die so there is life after a Servername ...
    print " (Extracted  domain name = [$domain] )" ; 
    if ( not exists $address{$domain} ) { # domain -> addr mapping?
       print  "\nNo IP address known for $domain\n" .
	     "Following section rejected" ;
       show ;
       unshift @section, "# NOT UPDATED because of unresolvable domain name\n" ;
       write_rejects ; # write section to rejected file
       write_section ; # but still write to output file
       return ;
    }

    # $section[0] is  first element of opening '<Virtualhost 1.2.3.4:80>'
    if ( $section[0] =~ m/^\s*<VirtualHost\s+(\d+\.\d+\.\d+.\d+)(:\d+)?\s*>/ ) {
        $ip = $1 ;
        $port = $2 ;
        if ( $debug == 1 ) { 
	    print  "\nProcessing: $section[0]" ; 
	    print " ( Extracted IP number:  $ip )" ;
	    print " Port number = $port " ;
	}
 
        if ( $ip eq $address{$domain} ) {
            if ( $debug == 1 ) {
		print  "\n======= No change for $domain at $ip ======" ;
		#show ;
		#print  "\n======= end of unchanged section ==========" ;
	        }	
            write_section ;
	    return ;
        }
        else {
            print  "\nChanging $ip -> $address{$domain}" ;
            $section[0] =~ s/\d+\.\d+\.\d+\.\d+(:\d+)?/$address{$domain}$port/ ;
	    print  "\nResult: $section[0]" ;
	    write_section ;
        }
     
    } else { die "Panic: Aborting processing ... No <VirtualHost> entry found!" ; }  
} # end sub process_section

# scan @section array for ServerName directive
sub get_ServerName {
    if ( $debug == 1 ) { print "\nScanning section for ServerName\n" ; }
    for (@section) {
        print "$_" ;
	if ( /^\s*ServerName\s+(\S+)$/ ) {
	    if ($debug == 1 ) { print  "Processing : $_" ; } 
            return $1 ;
	}
    }
}

# --- read  "domain -> IPaddr" mappings file and store in hash table %address
sub get_mapping {
    my ($domain, $ip ) ;
    my $file = 'domain-addr.txt' ;
    open ( FILE, "< $file" ) or die "Cannot open $file"  ; 
    while ( <FILE> ) {
        chomp ; # get rid of LF
        ($domain, $ip) = split /=/ ;
        #print   "\nDomain: [$domain] IP: [$ip]" ;
        if ( $ip eq "" ) {
            print  "\nDomain $domain has no IP address. Skipping $domain ..." ; 
        next ;
        }
    $address{$domain} = $ip ;
    }
}

sub show {
   for  (@section) {
        print "\n--$_" ;
   }
}

sub write_section {
    for (@section) {
	print RESULT ; # print implied $_
    } 
}

sub write_rejects {
    for (@section) {
	print REJECT ; # print implied $_
    } 
}

# --- main
get_mapping ;	# read file 'domain-addr.txt' into %address hash

open ( RESULT, "> virt_updated.txt" ) or die "Cannot open updated.txt!" ;
open ( REJECT, "> virt_rejects.txt" ) or die "Cannot open updated.txt!" ;

# output  (only to see synchronized debugging messages)
$debug = 1 ;

if ( $debug == 1 ) { 
    $| = 1 ; # enable autoflush for synced debugging stuff 
} 

parse ;

print <<EOF ;

---- Message
Updated file : virt_updated.txt
A copy of unmodified sections because of unknown IP address : virt_rejects.txt

To see the differences run    
   
    diff -u name_of_original_file  virt_updated.txt

--- End of message
EOF

END { close RESULT ; close REJECT ; }
You have to tell it, which virtual host config file to use. It will not modify this file at all. It will produce a modified version in the file "virt-updated.txt'.
The domains for which the 'domain-addr.txt' has found no IP address, the virtual hosts sections will be copied to the file "virt-updated.txt'.
An extra copy will be written to the file 'virt_rejects.txt'.

So here we go:
Code:
$ ./virt-update virt_orig.txt
The debugging code will show this for the last section
Code:
Scanning section for ServerName
<VirtualHost 4.4.4.4:8080>
    #
    # Our forum
    # 
    ServerName daemonforums.org
Processing :     ServerName daemonforums.org
 (Extracted  domain name = [daemonforums.org] )
Processing: <VirtualHost 4.4.4.4:8080>
 ( Extracted IP number:  4.4.4.4 ) Port number = :8080 
Changing 4.4.4.4 -> 67.205.67.40
Result: <VirtualHost 67.205.67.40:8080>
To see the changes you can run diff to compare the new file with the original
Code:
$ diff -u virt_orig.txt virt_updated.txt
--- virt_orig.txt       Mon Nov 24 02:41:22 2008
+++ virt_updated.txt    Mon Nov 24 03:19:52 2008
@@ -1,25 +1,25 @@
 # start of virtual hosts
-<VirtualHost 11.11.11.11:80>
+<VirtualHost 145.7.192.133:80>
     ServerName kpn.com
     ServerAlias www.kpn.com
 </VirtualHost>
 
 # a remark preceded by an empty line
-<VirtualHost 22.22.22.22:80>
+<VirtualHost 128.121.215.221:80>
     # ServerName fish.org 
     ServerName gorilla.org
     ServerAlias www.gorilla.org
 </VirtualHost>
 # another remark followed by an empty line
 
-<VirtualHost 33.33.33.33:8080>
+<VirtualHost 152.160.49.201:8080>
     # --- home of the monkeys
     ServerName monkey.org
     ServerAlias www.monkey.org
     ServerAdmin webmaster@monkey.org
 </VirtualHost>
 
-<VirtualHost 4.4.4.4:8080>
+<VirtualHost 67.205.67.40:8080>
     #
     # Our forum
     #
In this case there were no rejects
Code:
$ ls -l virt*txt 
-rw-r--r--  1 j65nko  j65nko  680 Nov 24 02:41 virt_orig.txt
-rw-r--r--  1 j65nko  j65nko    0 Nov 24 03:19 virt_rejects.txt
-rw-r--r--  1 j65nko  j65nko  694 Nov 24 03:19 virt_updated.txt
To uncompress the attached file
Code:
$ tar xvzf virt-updater.tgz
Attached Files
File Type: tgz virt-updater.tgz (2.6 KB, 72 views)
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump

Last edited by J65nko; 24th November 2008 at 02:32 AM. Reason: Attach file
Reply With Quote