@ -23,9 +23,6 @@ from webserver import BorderCheckWebserver
from xml_exporter import xml_reporting
from xml_exporter import xml_reporting
import webbrowser
import webbrowser
# set to emit debug messages about errors (0 = off).
DEBUG = 1
class bc ( object ) :
class bc ( object ) :
"""
"""
BC main Class
BC main Class
@ -96,17 +93,21 @@ class bc(object):
try :
try :
return func ( * args )
return func ( * args )
except Exception as e :
except Exception as e :
print ( " \n [Error] - Something wrong fetching urls. Aborting... " ) , " \n "
if not options . debug :
if DEBUG :
print ( " [Error] - Something wrong happens!. Try to run again with --debug option to see more detailed information about the error on a Traceback output. " ) , " \n "
else :
print ( " [Error] - Something wrong happens!. You have the reason at the end of the Traceback. If you don ' t understand what ' s happen, try to contact with project contributors. " ) , " \n "
if options . debug == 1 :
traceback . print_exc ( )
traceback . print_exc ( )
sys . exit ( 2 )
print " " # \n after traceback ouput
sys . exit ( 2 )
def check_root ( self ) :
def check_root ( self ) :
"""
"""
Check root permissions
Check root permissions
"""
"""
if not os . geteuid ( ) == 0 :
if not os . geteuid ( ) == 0 :
sys . exit ( " \n Only root can run this script... \n " )
sys . exit ( " Warning: Only root can launch traceroutes. (Try: ' sudo ./bc ' ) \n " )
def check_browser ( self ) :
def check_browser ( self ) :
"""
"""
@ -384,7 +385,10 @@ class bc(object):
print " Can ' t get Safari version information, you ' ll have to look it up manually \n "
print " Can ' t get Safari version information, you ' ll have to look it up manually \n "
else :
else :
print " Version: " , self . browser_version
print " Version: " , self . browser_version
print " History: " , self . browser_history_path , " \n "
if self . options . import_xml : # history not needed on xml importing
pass
else :
print " History: " , self . browser_history_path , " \n "
def getURL ( self ) :
def getURL ( self ) :
"""
"""
@ -429,6 +433,9 @@ class bc(object):
"""
"""
Run an LFT
Run an LFT
"""
"""
# LFT needs root
root = self . try_running ( self . check_root , " \n Internal error checking root permissions. " )
#try:
#try:
if self . operating_system == ' darwin ' :
if self . operating_system == ' darwin ' :
try :
try :
@ -438,13 +445,13 @@ class bc(object):
self . content = a . stdout . read ( )
self . content = a . stdout . read ( )
if self . operating_system == ' linux ' :
if self . operating_system == ' linux ' :
if self . method == ' -e ' :
if self . method == ' -e ' : # tcp probes
self . method = ' -E '
self . method = ' -E '
try :
try :
self . content = subprocess . check_output ( [ ' lft ' , ' -S ' , ' -n ' , self . destination_ip ] )
self . content = subprocess . check_output ( [ ' lft ' , ' -S ' , ' -n ' , self . method , self . destination_ip ] )
# support for older python versions (<2.75) that don't support subprocess.check_output
# support for older python versions (<2.75) that don't support subprocess.check_output
except :
except :
a = subprocess . Popen ( [ ' lft ' , ' -S ' , ' -n ' , self . destination_ip ] , stdout = subprocess . PIPE )
a = subprocess . Popen ( [ ' lft ' , ' -S ' , ' -n ' , self . method , self . destination_ip ] , stdout = subprocess . PIPE )
self . content = a . stdout . read ( )
self . content = a . stdout . read ( )
self . attempts + = 1
self . attempts + = 1
if self . options . debug == True :
if self . options . debug == True :
@ -524,7 +531,7 @@ class bc(object):
for ip in line :
for ip in line :
if re . match ( r ' \ d { 1,4} \ . \ dms$ ' , ip ) :
if re . match ( r ' \ d { 1,4} \ . \ dms$ ' , ip ) :
self . timestamp = ip . replace ( ' ms ' , ' ' )
self . timestamp = ip . replace ( ' ms ' , ' ' )
if re . match ( r ' ^127 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , ip ) or re . match ( r ' ^10 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , ip ) or re . match ( r ' ^192.168 \ . \ d { 1,3} \ . \ d { 1,3}$ ' , ip ) or re . match ( r ' ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9] { 1,3}.[0-9] { 1,3}$ ' , ip ) :
if re . match ( r ' ^127 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , ip ) or re . match ( r ' ^10 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , ip ) or re . match ( r ' ^192.168 \ . \ d { 1,3} \ . \ d { 1,3}$ ' , ip ) or re . match ( r ' ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9] { 1,3}.[0-9] { 1,3}$ ' , ip ) or re . match ( ' localhost ' , ip ) :
pass
pass
else :
else :
if re . match ( r " ^ \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ " , ip ) :
if re . match ( r " ^ \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ " , ip ) :
@ -639,6 +646,45 @@ class bc(object):
os . remove ( ' GeoIPASNum.gz ' )
os . remove ( ' GeoIPASNum.gz ' )
print " Database: GeoIPASNum \n "
print " Database: GeoIPASNum \n "
def importXML ( self ) :
"""
Import travels data directly from XML file ( no root needed ) and launch a web browser on a thread with a map showing them .
"""
try :
xml_results = xml_reporting ( self )
xml_imported = xml_results . read_xml_results ( ) # read xml directly from file
except :
print ( " [Error] - Something wrong importing data from XML file. Aborting... " ) , " \n "
sys . exit ( 2 )
# Set the maxmind geo databases
self . geoip = pygeoip . GeoIP ( ' GeoLiteCity.dat ' )
self . geoasn = pygeoip . GeoIP ( ' GeoIPASNum.dat ' )
match_ip = xml_imported [ 0 ] . strip ( ' http:// ' ) . strip ( ' :8080 ' )
#regex for filtering local network IPs
if re . match ( r ' ^127 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^10 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^192.168 \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9] { 1,3}.[0-9] { 1,3}$ ' , match_ip ) or match_ip . startswith ( ' file:// ' ) or match_ip . startswith ( ' localhost ' ) :
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print " URL: " , self . options . import_xml , " \n "
print " Warning: This target is not valid!. \n "
sys . exit ( 2 )
else :
if xml_imported [ 0 ] . startswith ( ' file:// ' ) :
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print " URL: " , self . options . import_xml , " \n "
print " Warning: This target is not valid!. \n "
sys . exit ( 2 )
else :
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print " URL: " , self . options . import_xml , " \n "
print " Host: " , xml_imported [ 0 ] , " \n "
os . system ( ' cp -r ' + self . options . import_xml + ' data.xml ' ) # copy XML data provided by user to data.xml template
# start web mode (on a different thread)
try :
webbrowser . open ( ' http://127.0.0.1:8080 ' , new = 1 )
BorderCheckWebserver ( self )
except ( KeyboardInterrupt , SystemExit ) :
sys . exit ( )
def run ( self , opts = None ) :
def run ( self , opts = None ) :
"""
"""
Run BorderCheck
Run BorderCheck
@ -653,77 +699,78 @@ class bc(object):
print ( ' = ' * 75 )
print ( ' = ' * 75 )
print ( str ( p . version ) )
print ( str ( p . version ) )
print ( ' = ' * 75 )
print ( ' = ' * 75 )
# root checker
root = self . try_running ( self . check_root , " \n Internal error checking root permissions. " )
# extract browser type and path
# extract browser type and path
browser = self . try_running ( self . check_browser , " \n Internal error checking browser files path. " )
browser = self . try_running ( self . check_browser , " \n Internal error checking browser files path. " )
# extract url
# extract url
url = self . try_running ( self . getURL , " \n Internal error getting urls from browser ' s database. " )
url = self . try_running ( self . getURL , " \n Internal error getting urls from browser ' s database. " )
# set geoip database
# set geoip database
geo = self . try_running ( self . getGEO , " \n Internal error setting geoIP database. " )
geo = self . try_running ( self . getGEO , " \n Internal error setting geoIP database. " )
# run traceroutes
# read from XML or run traceroutes + stay latent mode
match_ip = self . url [ 0 ] . strip ( ' http:// ' ) . strip ( ' :8080 ' )
if options . import_xml :
#regex for filtering local network IPs
import_xml = self . try_running ( self . importXML , " \n Internal error importing XML data from file. " )
if re . match ( r ' ^127 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^10 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^192.168 \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9] { 1,3}.[0-9] { 1,3}$ ' , match_ip ) or match_ip . startswith ( ' file:// ' ) :
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print " URL: " , self . url [ 0 ] , " \n "
print " Warning: This target is not valid!. \n "
pass
else :
else :
if self . url [ 0 ] . startswith ( ' file:// ' ) :
match_ip = self . url [ 0 ] . strip ( ' http:// ' ) . strip ( ' :8080 ' )
#regex for filtering local network IPs
if re . match ( r ' ^127 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^10 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^192.168 \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9] { 1,3}.[0-9] { 1,3}$ ' , match_ip ) or match_ip . startswith ( ' file:// ' ) or match_ip . startswith ( ' localhost ' ) :
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print " URL: " , self . url [ 0 ] , " \n "
print " URL: " , self . url [ 0 ] , " \n "
print " Warning: This target is not valid!. \n "
print " Warning: This target is not valid!. \n "
pass
pass
else :
else :
traces = self . try_running ( self . traces , " \n Internal error tracerouting. " )
if self . url [ 0 ] . startswith ( ' file:// ' ) :
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print " URL: " , self . url [ 0 ] , " \n "
print " Warning: This target is not valid!. \n "
pass
else :
traces = self . try_running ( self . traces , " \n Internal error tracerouting. " )
# start web mode (on a different thread)
# start web mode (on a different thread)
try :
t = threading . Thread ( target = BorderCheckWebserver , args = ( self , ) )
t . daemon = True
t . start ( )
time . sleep ( 2 )
except ( KeyboardInterrupt , SystemExit ) :
t . join ( )
sys . exit ( )
# open same browser of history access on a new tab
try :
try :
webbrowser . open ( ' http://127.0.0.1:8080 ' , new = 1 )
t = threading . Thread ( target = BorderCheckWebserver , args = ( self , ) )
except :
t . daemon = True
print " Error: Browser is not responding correctly. \n "
t . start ( )
time . sleep ( 2 )
except ( KeyboardInterrupt , SystemExit ) :
t . join ( )
sys . exit ( )
# open same browser of history access on a new tab
try :
webbrowser . open ( ' http://127.0.0.1:8080 ' , new = 1 )
except :
print " Error: Browser is not responding correctly. \n "
print ( ' = ' * 75 )
print ( ' = ' * 75 )
print ( str ( p . version ) )
print ( str ( p . version ) )
print ( ' = ' * 75 + " \n " )
print ( ' = ' * 75 + " \n " )
print " Status: Waiting for new urls ... \n "
print " Status: Waiting for new urls ... \n "
print " Type ' Control+C ' to exit. \n "
print " Type ' Control+C ' to exit. \n "
# stay latent waiting for new urls
# stay latent waiting for new urls
while True :
while True :
url = urlparse ( self . getURL ( ) ) . netloc
url = urlparse ( self . getURL ( ) ) . netloc
#url = url.replace('www.','')
#url = url.replace('www.','')
try :
try :
match_ip = url . strip ( ' http:// ' ) . strip ( ' :8080 ' )
match_ip = url . strip ( ' http:// ' ) . strip ( ' :8080 ' )
except :
except :
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print ' = ' * 45 + " \n " , " Target: \n " + ' = ' * 45 + " \n "
print " URL: " , self . url [ 0 ] , " \n "
print " URL: " , self . url [ 0 ] , " \n "
pass
if url != self . old_url :
if re . match ( r ' ^127 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^10 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^192.168 \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9] { 1,3}.[0-9] { 1,3}$ ' , match_ip ) :
pass
pass
else :
if url != self . old_url :
if self . url [ 0 ] . startswith ( ' file:// ' ) :
if re . match ( r ' ^127 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^10 \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^192.168 \ . \ d { 1,3} \ . \ d { 1,3}$ ' , match_ip ) or re . match ( r ' ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9] { 1,3}.[0-9] { 1,3}$ ' , match_ip ) or match_ip . startswith ( ' localhost ' ) :
pass
pass
else :
else :
if os . path . exists ( ' data.xml ' ) : # removing xml data to has a new map each time that bc is launched
if self . url [ 0 ] . startswith ( ' file:// ' ) :
os . remove ( ' data.xml ' )
pass
open ( ' data.xml ' , ' w ' ) # starting a new xml data container in write mode
else :
traces = self . try_running ( self . traces , " \n Internal error tracerouting. " )
if os . path . exists ( ' data.xml ' ) : # removing xml data to has a new map each time that bc is launched
# open same browser of history access on a new tab
os . remove ( ' data.xml ' )
# try:
open ( ' data.xml ' , ' w ' ) # starting a new xml data container in write mode
# webbrowser.open('http://127.0.0.1:8080', new=2) # open on same tab?
traces = self . try_running ( self . traces , " \n Internal error tracerouting. " )
# except:
# open same browser of history access on a new tab
# print "Error: Browser is not responding correctly.\n"
# try:
time . sleep ( 5 ) # free process time or goodbye :-)
# webbrowser.open('http://127.0.0.1:8080', new=2) # open on same tab?
# except:
# print "Error: Browser is not responding correctly.\n"
time . sleep ( 5 ) # free process time or goodbye :-)
if __name__ == " __main__ " :
if __name__ == " __main__ " :
app = bc ( )
app = bc ( )