[tor-commits] r26291: {} fork torcheck to make a (much faster) version that doesn't a (check/trunk/cgi-bin)

Roger Dingledine arma at torproject.org
Fri Aug 9 15:24:27 UTC 2013


Author: arma
Date: 2013-08-09 15:24:27 +0000 (Fri, 09 Aug 2013)
New Revision: 26291

Added:
   check/trunk/cgi-bin/TorCheck-off.py
Log:
fork torcheck to make a (much faster) version that doesn't actually check


Copied: check/trunk/cgi-bin/TorCheck-off.py (from rev 26290, check/trunk/cgi-bin/TorCheck.py)
===================================================================
--- check/trunk/cgi-bin/TorCheck-off.py	                        (rev 0)
+++ check/trunk/cgi-bin/TorCheck-off.py	2013-08-09 15:24:27 UTC (rev 26291)
@@ -0,0 +1,351 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+ TorCheck.py
+
+ https://check.torproject.org - originally in perl, rewritten in python
+
+ By Jacob Appelbaum <jacob at appelbaum.net>
+ Written at ToorCon Seattle 2008 (Thanks for the great time h1kari!)
+ Thanks to Crispen for a power outlet :-)
+ 
+ Additional python suggestions from nickm
+ 
+ Best used with the Debian packages:
+    python-dns
+    libapache2-mod-python
+    locales-all
+
+"""
+
+__program__ = 'TorCheck.py'
+__version__ = '20100429.01'
+__url__ = 'https://svn.torproject.org/svn/check/'
+__author__ = 'Jacob Appelbaum <jacob at appelbaum.net>'
+__copyright__ = 'Copyright (c) 2008, Jacob Appelbaum'
+__license__ = 'See LICENSE for licensing information'
+
+try:
+    from future import antigravity
+except ImportError:
+    antigravity = None
+
+import cgi
+import DNS
+from DNS import DNSError
+# This is pydns and can be downloaded from http://pydns.sourceforge.net/ 
+# Or use the Debian package listed above
+import cgitb; cgitb.enable()
+import gettext
+import locale
+import os
+
+#os.environ['LOCPATH']='/usr/share/locale:/srv/check.torproject.org/trunk/i18n/locale'
+localedir ='/srv/check.torproject.org/trunk/i18n/locale'
+
+# We could also explictly query the remote EL server
+# This is not as good as using a cache for obvious reasons
+DNS.DiscoverNameServers()
+
+def isUsingTor(clientIp, ELPort):
+    # This is the exit node ip address
+    # This is where we want to dynamically recieve this from Apache
+    splitIp = clientIp.split('.')
+    splitIp.reverse()
+    ELExitNode = ".".join(splitIp)
+
+    # We'll attempt to reach this port on the Target host
+    # ELPort is now set by the caller
+
+    # We'll try to reach this host
+    ElTarget = "38.229.70.31"
+
+    # This is the ExitList DNS server we want to query
+    ELHost = "ip-port.exitlist.torproject.org"
+
+    # Prepare the question as an A record request
+    ELQuestion = ELExitNode + "." + ELPort + "." + ElTarget + "." + ELHost 
+    request = DNS.DnsRequest(name=ELQuestion,qtype='A')
+
+    # Ask the question and load the data into our answer
+    try:
+      answer=request.req()
+    except DNSError:
+      return 2
+
+    # Parse the answer and decide if it's allowing exits
+    # 127.0.0.2 is an exit and NXDOMAIN is not
+    if answer.header['status'] == "NXDOMAIN":
+        # We're not exiting from a Tor exit
+        return 1
+    else:
+        if not answer.answers:
+            # We're getting unexpected data - fail closed
+            return 2
+        for a in answer.answers:
+            if a['data'] != "127.0.0.2":
+                return 2
+        # If we're here, we've had a positive exit answer
+        return 0
+
+
+def isUpToDate(queryString):
+    """
+    determine if TBB is aware of newer versions
+    """
+    if 'uptodate=1' in queryString.lower():
+        return True
+    if 'uptodate=0' in queryString.lower():
+        return False
+    # This will be true until Torbutton 1.4.4 is released
+    if 'small=1' in queryString.lower():
+        return False
+    
+    # The default case; No update information to provide
+    return True
+
+
+def getLocales():
+    locale_descriptions = {
+    'ar' : 'عربية (Arabiya)',
+    'bms' : 'Burmese',
+    'cs' : 'česky',
+    'da' : 'dansk',
+    'de' : 'Deutsch',
+    'el' : 'Ελληνικά (Ellinika)',
+    'en_US' : 'English',
+    'es' : 'español',
+    'et' : 'Estonian',
+    'fa_IR' : 'فارسی (Fārsī)',
+    'fr' : 'français',
+    'it_IT' : 'Italiano',
+    'ja' : '日本語 (Nihongo)',
+    'nb' : 'norsk (bokmål)',
+    'nl' : 'Nederlands',
+    'pl' : 'polski',
+    'pt' : 'Português',
+    'pt_BR' : 'Português do Brasil',
+    'ro' : 'română',
+    'fi' : 'suomi',
+    'ru' : 'Русский (Russkij)',
+    'th' : 'Thai',
+    'tr' : 'Türkçe',
+    'uk' : 'українська (ukrajins\'ka)',
+    'vi' : 'Vietnamese',
+    'zh_CN' : '中文(简)' }
+    return locale_descriptions
+
+def getLocaleName(lang):
+    # If the user passes in a locale that matches what we support, good
+    # However, anything that we don't support will result in us using a default locale
+    # 
+    # Important! lang is tainted data, don't forget this!
+    #
+    
+    default_locale = "en_US"
+
+    # We'd really like these additional locales to be translated:
+    # locales = ( 'ar', 'fr', 'nl', 'pt-PT', 'ru' )
+
+    # Make sure we have a valid language
+    if not lang:
+        return default_locale
+
+    # This is to deal with Mozilla and Debian having different ideas about
+    # what it means to be a locale
+    lang = lang.replace("-", "_")
+
+    # Do a case insensitive match
+    lang = lang.lower()
+
+    # Check for an exact match of language_country
+    for item in getLocales().keys():
+        if item.lower() == lang:
+            return item
+
+    # Check for just the language
+    lang = lang.split("_", 1)[0]
+    for item in getLocales().keys():
+        if item.lower().startswith(lang):
+            return item    
+
+    # Fall back to default
+    return default_locale
+    
+def showLogo(formSubmission):
+    # By default, we'll show a logo
+    show_logo = True
+    hide_logo = formSubmission.getfirst("small", None)
+    # hide_logo isn't cleaned - do not use it for anything else
+    if hide_logo:
+        return False 
+    return show_logo
+
+def parseLang(formSubmission):
+    user_supplied_lang = formSubmission.getfirst("lang", None)
+
+    # Find the best match for the requested language
+    locale = getLocaleName(user_supplied_lang)
+
+    # i18n with Unicode!
+    # Ensure you have properly installed TorCheck.{po,pot,mo} files
+    lang = gettext.translation('TorCheck', localedir=localedir, languages=[locale], fallback=True)
+    lang.install()
+
+def printTorButton(req, UsingTor):
+    req.write('<html xmlns="http://www.w3.org/1999/xhtml"><body>')
+    if UsingTor == 0:
+        req.write('<a id="TorCheckResult" target="success" href="/"></a>')
+    elif UsingTor == 1:
+        req.write('<a id="TorCheckResult" target="failure" href="/"></a>\n')
+    else:
+        req.write('<a id="TorCheckResult" target="unknown" href="/"></a>\n')
+    req.write('</body></html>')
+
+# Now that we know everything we need, lets print the website
+def handler(req, environ, start_response):
+    # Make a DNS request to the EL and decide what to tell the user
+    UsingTor = isUsingTor(environ['REMOTE_ADDR'], "80")
+    # Try to hit a cornercase where the user can exit to 443 but not 80
+    if UsingTor != 0:
+        UsingTor = isUsingTor(environ['REMOTE_ADDR'], "443")
+
+    # figure out if the client passed uptodate=0 or uptodate=1
+    # defaults to 1 if uptodate was not present in the query string
+    UpToDate = isUpToDate(environ['QUERY_STRING'])
+
+    response_headers = [('Content-type', 'text/html; charset=utf-8')]
+    start_response('200 OK', response_headers)
+
+    # We want to catch TorButton queries so they don't output overhead
+    # This is to make all the data fit into one cell
+    formSubmission = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
+    if formSubmission.getfirst("TorButton", None):
+        printTorButton(req, UsingTor)
+        return
+
+    # First lets construct the simple webpage:
+    req.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '\
+    '"http://www.w3.org/TR/REC-html40/loose.dtd">\n')
+    req.write('<html>\n')
+    req.write('<head>\n')
+    req.write('<meta http-equiv="content-type" content="text/html; '\
+    'charset=utf-8">\n')
+    req.write('<title>Are you using Tor?</title>\n')
+    req.write('<link rel="shortcut icon" type="image/x-icon" '\
+    'href="./favicon.ico">\n')
+    req.write('<style type="text/css">\n')
+    req.write('img,acronym {\n')
+    req.write('  border: 0;')
+    req.write('  text-decoration: none;')
+    req.write('}')
+    req.write('</style>')
+    req.write('</head>\n')
+    req.write('<body>\n')
+
+    parseLang(formSubmission)
+    hideLogo = showLogo(formSubmission)
+
+    req.write('<center>\n')
+
+    if UsingTor == 0:
+        if UpToDate:
+            req.write('\n')
+            if hideLogo:
+                req.write('<img alt="' + _("Congratulations. Your browser is configured to use Tor.") + \
+                '" src="/images/tor-on.png">\n<br>')
+            req.write('<h1 style="color: #0A0">\n')
+            req.write(_('Congratulations. Your browser is configured to use Tor.'))
+            req.write('<br>\n<br>\n')
+            req.write('</h1>\n')
+            req.write(_('Please refer to the <a href="https://www.torproject.org/">Tor website</a> for further information about using Tor safely.  You are now free to browse the Internet anonymously.'))
+            req.write('<br>\n<br>\n')
+        else:
+            req.write('\n')
+            if hideLogo:
+                req.write('<img alt="' + _("Congratulations. Your browser is configured to use Tor.") + \
+                '" src="/images/tor-on.png">\n<br>')
+            req.write('<h1 style="color: #0A0">\n')
+            req.write(_('Congratulations. Your browser is configured to use Tor.'))
+            req.write('<br>\n<br>\n')
+            req.write('</h1>\n')
+            req.write('<h1 style="color: #FA0">\n')
+            req.write(_('There is a security update available for the Tor Browser Bundle.'))
+            req.write('<br>\n<br>\n')
+            req.write(_('<a href="https://www.torproject.org/download/download-easy.html">Click here to go to the download page</a>'))
+            req.write('<br>\n<br>\n')
+            req.write('</h1>\n')  
+            req.write(_('Please refer to the <a href="https://www.torproject.org/">Tor website</a> for further information about using Tor safely.  You are now free to browse the Internet anonymously.'))
+            req.write('<br>\n<br>\n') 
+    
+    # This is the case where we have an NXDOMAIN and they aren't using Tor
+    elif UsingTor == 1:
+        req.write('\n')
+        if hideLogo:
+            req.write('<img alt="' + _("Sorry. You are not using Tor.") + '" '\
+            'src="/images/tor-off.png">\n<br>')
+        req.write('<h1 style="color: #A00">')
+        req.write(_('Sorry. You are not using Tor.'))
+        req.write('<br>\n<br>\n')
+        req.write('</h1>')
+        req.write(_('If you are attempting to use a Tor client, please refer to the <a href="https://www.torproject.org/">Tor website</a> and specifically the <a href="https://www.torproject.org/docs/faq#DoesntWork">instructions for configuring your Tor client</a>.'))
+        req.write('<br>\n<br>\n')
+
+    # This means we have some strange data response we don't understand
+    # It's better that we fail closed and let the user know everything went wrong
+    elif UsingTor == 2:
+        req.write('\n')
+        req.write('<img alt="' + _("Sorry, your query failed or an unexpected response was received.") + '" '\
+        'src="/images/tor-off.png">\n<br>')
+        req.write('<h1 style="color: #A00">\n')
+        req.write(_('Sorry, your query failed or an unexpected response was received.'))
+        req.write('<br>\n')
+        req.write('</h1>')
+        req.write(_('A temporary service outage prevents us from determining if your source IP address is a <a href="https://www.torproject.org/">Tor</a> node.'))
+        req.write('<br>\n<br>\n')
+
+    # Now we'll close up this html rat hole
+    req.write('\n')
+    req.write('<br>\n');
+    req.write(_('Your IP address appears to be: '))
+    req.write('<b>%s</b><br>\n' % environ['REMOTE_ADDR'] )
+    req.write('<small>\n')
+    req.write('<tt>')
+#    req.write(_('Additional information: '))
+#    req.write('<br>\n')
+#    req.write(_('This small script is powered by <a href="http://exitlist.torproject.org/">tordnsel</a>'))
+#    req.write('<br>')
+#    req.write(_('You may also be interested in the <a href="/cgi-bin/TorBulkExitList.py">Tor Bulk Exit List Exporter</a>'))
+#    req.write('<br><br>')
+#    req.write(_('This server does not log <i>any</i> information about visitors.'))
+    req.write('<br>\n<br>\n')
+    # We want to display little pretty images so users can choose their language
+    locales = getLocales()
+
+    req.write('<p>This page is also available in the following languages:')
+    req.write('</p><p>')
+    for item in sorted(locales.keys()):
+        req.write('<a href="?lang=%s" ' % item )
+        req.write('hreflang="%s" ' % item )
+        req.write('lang="%s" rel="alternate">' % item )
+        req.write('%s</a> ' % locales[item] )
+    req.write('</p>')
+    req.write('</tt>')
+    req.write('</small>')
+    req.write('</center>\n')
+    req.write('</body>')
+    req.write('</html>')
+
+
+class FakeReq(list):
+    def write(self, str):
+        self.append(str)
+
+def application(environ, start_response):
+    req = FakeReq()
+    handler(req, environ, start_response)
+    return req
+
+# vim:set ts=4:
+# vim:set et:
+# vim:set shiftwidth=4:



More information about the tor-commits mailing list