Ejemplo n.º 1
0
def file_header(code, size, protocol='1.1'):
    date = time.strftime('%c %Z')
    version = load().proxy.version

    return '\r\n'.join([
        'HTTP/%s %s %s' % (protocol, str(code), _HTTP_NAMES.get(code, '-')),
        'Date: %s' % date,
        'Server: exaproxy/%s (%s)' % (str(version), str(sys.platform)),
        'Content-Length: %d' % size, 'Connection: close',
        'Content-Type: text/html', 'Cache-Control: no-store',
        'Pragma: no-cache', ''
    ])
Ejemplo n.º 2
0
def http(code, message, protocol='1.1'):
    encoding = 'html' if message[:5].lower().startswith('<html') else 'plain'
    date = time.strftime('%c %Z')
    version = load().proxy.version

    return '\r\n'.join([
        'HTTP/%s %s %s' % (protocol, str(code), _HTTP_NAMES.get(code, '-')),
        'Date: %s' % date,
        'Server: exaproxy/%s (%s)' % (str(version), str(sys.platform)),
        'Content-Length: %d' % len(message),
        'Content-Type: text/%s' % encoding, 'Cache-Control: no-store',
        'Pragma: no-cache', '', message
    ])
Ejemplo n.º 3
0
def file_header(code, size, name, protocol='1.1'):
	date = time.strftime('%c %Z')
	version = load().proxy.version

	return '\r\n'.join([
		'HTTP/%s %s %s' % (protocol, str(code), _HTTP_NAMES.get(code,'-')),
		'Date: %s' % date,
		'Server: exaproxy/%s (%s)' % (str(version), str(sys.platform)),
		'Content-Length: %d' % size,
		'Connection: close',
		'Content-Type: text/html',
		'Cache-Control: no-store',
		'Pragma: no-cache',
		''
	])
Ejemplo n.º 4
0
def http (code,message, protocol='1.1'):
	encoding = 'html' if message[:5].lower().startswith('<html') else 'plain'
	date = time.strftime('%c %Z')
	version = load().proxy.version

	return '\r\n'.join([
		'HTTP/%s %s %s' % (protocol, str(code), _HTTP_NAMES.get(code,'-')),
		'Date: %s' % date,
		'Server: exaproxy/%s (%s)' % (str(version), str(sys.platform)),
		'Content-Length: %d' % len(message),
		'Content-Type: text/%s' % encoding,
		'Cache-Control: no-store',
		'Pragma: no-cache',
		'',
		message
	])
Ejemplo n.º 5
0
# encoding: utf-8
"""
async/__init__.py

Created by David Farrar on 2012-01-31.
Copyright (c) 2011-2013  Exa Networks. All rights reserved.
"""

import sys
import select

from exaproxy.util.log.logger import Logger
from exaproxy.configuration import load

configuration = load()
log = Logger('supervisor', configuration.log.supervisor)


def Poller(configuration, speed=None):
    reactor = configuration.reactor

    if reactor == 'best':
        if sys.platform.startswith('linux'):
            configuration.reactor = 'epoll'
        elif sys.platform.startswith('freebsd'):
            configuration.reactor = 'kqueue'
        elif sys.platform.startswith('darwin'):
            configuration.reactor = 'kqueue'
        else:
            log.error(
                'we could not autodetect an high performance reactor for your OS'
Ejemplo n.º 6
0
nettools.py

Created by Thomas Mangin on 2011-11-30.
Copyright (c) 2011-2013  Exa Networks. All rights reserved.
"""

import socket
import errno

from exaproxy.util.log.logger import Logger
from exaproxy.network.errno_list import errno_block
from exaproxy.configuration import load

IP_TRANSPARENT = 19

configuration = load()
log = Logger('server', configuration.log.server)

def isipv4(address):
	try:
		socket.inet_pton(socket.AF_INET, address)
		return True
	except socket.error:
		return False

def isipv6(address):
	try:
		socket.inet_pton(socket.AF_INET6, address)
		return True
	except socket.error:
		return False
Ejemplo n.º 7
0
def main():
    main = int(sys.version[0])
    secondary = int(sys.version[2])

    if main != 2 or secondary < 4:
        sys.exit(
            'This program can not work (is not tested) with your python version (< 2.4 or >= 3.0)'
        )

    if main == 2 and secondary == 4:
        version_warning()

    from exaproxy.configuration import ConfigurationError, load, ini, env

    next = ''
    arguments = {
        'configuration': '',
    }

    for arg in sys.argv[1:]:
        if next:
            arguments[next] = arg
            next = ''
            continue
        if arg in ['-c', '--conf-file']:
            next = 'configuration'

    version = os.environ.get('exaproxy_release', 'unknown')

    defaults = {
        'tcp4': {
            'host': (value.unquote, string.quote, '127.0.0.1',
                     'the host the proxy listen on'),
            'port': (value.integer, string.nop, '3128',
                     'the port the proxy listen on'),
            'timeout':
            (value.integer, string.nop, '5',
             'time before we abandon inactive established connections'),
            'backlog':
            (value.integer, string.nop, '200',
             'when busy how many connection should the OS queue for us'),
            'listen': (value.boolean, string.lower, 'true',
                       'should we listen for connections over IPv4'),
            'out': (value.boolean, string.lower, 'true',
                    'allow connections to remote web servers over IPv4'),
            'bind': (value.unquote, string.quote, '0.0.0.0',
                     'which ipv4 to use when creating outbound connection'),
        },
        'tcp6': {
            'host': (value.unquote, string.quote, '::1',
                     'the host the proxy listen on'),
            'port': (value.integer, string.nop, '3128',
                     'the port the proxy listen on'),
            'timeout':
            (value.integer, string.nop, '5',
             'time before we abandon inactive established connections'),
            'backlog':
            (value.integer, string.nop, '200',
             'when busy how many connection should the OS queue for us'),
            'listen': (value.boolean, string.lower, 'false',
                       'should we listen for connections over IPv6'),
            'out': (value.boolean, string.lower, 'true',
                    'allow connections to remote web servers over IPv6'),
            'bind': (value.unquote, string.quote, '::',
                     'which ipv6 to use when creating outbound connection'),
        },
        'redirector': {
            'enable': (value.boolean, string.lower, 'false',
                       'use redirector programs to filter http request'),
            'program':
            (value.exe, string.path, 'etc/exaproxy/redirector/url-allow',
             'the program used to know where to send request'),
            'minimum': (value.integer, string.nop, '5',
                        'minimum number of worker threads (forked program)'),
            'maximum': (value.integer, string.nop, '25',
                        'maximum number of worker threads (forked program)'),
            'protocol':
            (value.redirector, string.quote, 'url',
             'what protocol to use (url -> squid like / icap:://<uri> -> icap like)'
             )
        },
        'http': {
            'idle-connect':
            (value.integer, string.nop, '300',
             'time before we abandon new inactive http client connections (0: unlimited)'
             ),
            'connections': (value.integer, string.nop, '32768',
                            'the maximum number of proxy connections'),
            'transparent': (value.boolean, string.lower, 'false',
                            'do not reveal the presence of the proxy'),
            'forward':
            (value.lowunquote, string.quote, '',
             'read client address from this header (normally x-forwarded-for)'
             ),
            'mask':
            (value.boolean, string.lower, 'false',
             'hide client address by removing the header specified in exaproxy.http.forward'
             ),
            'allow-connect':
            (value.boolean, string.lower, 'true',
             'allow client to use CONNECT and https connections'),
            'expect': (value.boolean, string.lower, 'false',
                       'block messages with EXPECT headers with a 417'),
            'extensions': (value.methods, string.list, '',
                           'allow new HTTP method (space separated)'),
            'proxied': (value.boolean, string.lower, 'false',
                        'request is encapsulated with haproxy proxy protocol'),
            'header-size':
            (value.integer, string.nop, '65536',
             'maximum size in bytes for HTTP headers (0 : unlimited)'),
        },
        'icap': {
            'enable':
            (value.boolean, string.lower, 'true', 'enable the icap server'),
            'host': (value.unquote, string.quote, '127.0.0.1',
                     'the address the icap server listens on'),
            'ipv6': (value.unquote, string.quote, '::',
                     'the ipv6 address the icap server listens on'),
            'port': (value.integer, string.nop, '1344',
                     'port the icap server listens on'),
            'idle-connect':
            (value.integer, string.nop, '300',
             'time before we abandon new inactive icap client connections (0: unlimited)'
             ),
            'connections': (value.integer, string.nop, '32768',
                            'the maximum number of icap connections'),
            'proxied': (value.boolean, string.lower, 'false',
                        'request is encapsulated with haproxy proxy protocol'),
            'header-size':
            (value.integer, string.nop, '65536',
             'maximum size in bytes for ICAP headers (0 : unlimited)'),
        },
        'web': {
            'enable': (value.boolean, string.lower, 'true',
                       'enable the built-in webserver'),
            'host': (value.unquote, string.quote, '127.0.0.1',
                     'the address the web server listens on'),
            'port': (value.integer, string.nop, '8080',
                     'port the web server listens on'),
            'html': (value.folder, string.path, 'etc/exaproxy/html',
                     'where internal proxy html pages are served from'),
            'connections': (value.integer, string.nop, '100',
                            'the maximum number of web connections'),
            'debug':
            (value.boolean, string.lower, 'false',
             'allow to debug the program via the web client (do not use in production)'
             ),
        },
        'daemon': {
            'identifier':
            (value.unquote, string.nop, 'ExaProxy',
             'a name for the log (to diferenciate multiple instances more easily)'
             ),
            'pidfile': (value.unquote, string.quote, '',
                        'where to save the pid if we manage it'),
            'user': (value.user, string.quote, 'nobody', 'user to run as'),
            'daemonize': (value.boolean, string.lower, 'false',
                          'should we run in the background'),
            'reactor':
            (value.unquote, string.quote, 'best',
             'event polling mechanism to use (select/epoll/kqueue/best)'),
            'speed': (value.integer, string.nop, '2',
                      'sleep duration when waiting for connection'),
            'poll-interfaces':
            (value.boolean, string.lower, 'true',
             'periodically poll for local addresses the proxy should not connect to'
             ),
        },
        'security': {
            'local':
            (value.services, string.services, '',
             'ip:port for allowed services (*:80 or 127.0.0.1:* allowed)'),
            'connect': (value.ports, string.list, '443 981 7000',
                        'ports allowed with CONNECT'),
        },
        'dns': {
            'resolver':
            (value.resolver, string.path, '/etc/resolv.conf', 'resolver file'),
            'timeout': (value.integer, string.nop, '2',
                        'how long to wait for DNS replies before retrying'),
            'retries': (value.integer, string.nop, '10',
                        'how many times to retry sending requests'),
            'ttl':
            (value.integer, string.nop, '900',
             'amount of time (in seconds) we will cache dns results for'),
            'fqdn': (value.boolean, string.lower, 'true',
                     'only resolve FQDN (hostnames must have a dot'),
            'definitions':
            (value.folder, string.path, 'etc/exaproxy/dns/types',
             'location of file defining dns query types'),
        },
        'log': {
            'enable':
            (value.boolean, string.lower, 'true', 'enable traffic logging'),
            'level':
            (value.syslog, string.syslog, 'ERROR',
             'log message with at least the priority logging.<level>'),
            'destination':
            (value.unquote, string.quote, 'stdout', 'where syslog should log'),
            'signal': (value.boolean, string.lower, 'true',
                       'log messages from the signal subsystem'),
            'configuration': (value.boolean, string.lower, 'true',
                              'log messages from the configuration subsystem'),
            'supervisor': (value.boolean, string.lower, 'true',
                           'log messages from the supervisor subsystem'),
            'daemon': (value.boolean, string.lower, 'true',
                       'log messages from the daemon subsystem'),
            'server': (value.boolean, string.lower, 'true',
                       'log messages from the server subsystem'),
            'client': (value.boolean, string.lower, 'true',
                       'log messages from the client subsystem'),
            'manager': (value.boolean, string.lower, 'true',
                        'log messages from the manager subsystem'),
            'worker': (value.boolean, string.lower, 'true',
                       'log messages from the worker subsystem'),
            'download': (value.boolean, string.lower, 'true',
                         'log messages from the download subsystem'),
            'http': (value.boolean, string.lower, 'true',
                     'log messages from the http subsystem'),
            'header': (value.boolean, string.lower, 'true',
                       'log messages from the header subsystem'),
            'resolver': (value.boolean, string.lower, 'true',
                         'log messages from the dns subsystem'),
            'web': (value.boolean, string.lower, 'true',
                    'log messages from the web subsystem'),
        },
        'usage': {
            'enable':
            (value.boolean, string.lower, 'false', 'enable traffic logging'),
            'destination':
            (value.unquote, string.quote, 'stdout', 'where syslog should log'),
        },
        'profile': {
            'enable':
            (value.boolean, string.lower, 'false', 'enable profiling'),
            'destination':
            (value.unquote, string.quote, 'stdout',
             'save profiling to file (instead of to the screen on exit)'),
        },
        'proxy': {
            'version': (value.nop, string.nop, version, 'ExaProxy\'s version'),
        },
        # Here for internal use
        'debug': {
            'memory': (value.boolean, string.lower, 'false',
                       'command line option --memory'),
            'pdb': (value.boolean, string.lower, 'false',
                    'command line option --pdb'),
            'log': (value.boolean, string.lower, 'false',
                    'command line option --debug'),
        },
    }

    try:
        configuration = load('exaproxy', defaults, arguments['configuration'])
    except ConfigurationError, e:
        print >> sys.stderr, 'configuration issue,', str(e)
        sys.exit(1)
Ejemplo n.º 8
0
def main ():
	primary = int(sys.version[0])
	secondary = int(sys.version[2])

	if primary != 2 or secondary < 4:
		sys.exit('This program can not work (is not tested) with your python version (< 2.4 or >= 3.0)')

	if primary == 2 and secondary == 4:
		version_warning()

	from exaproxy.configuration import ConfigurationError,load,ini,env

	followup = ''
	arguments = {
		'configuration' : '',
	}

	for arg in sys.argv[1:]:
		if followup:
			arguments[followup] = arg
			followup = ''
			continue
		if arg in ['-c','--conf-file']:
			followup = 'configuration'

	defaults = {
		'tcp4' : {
			'host'    : (value.unquote,string.quote,'127.0.0.1', 'the host the proxy listen on'),
			'port'    : (value.integer,string.nop,'3128',        'the port the proxy listen on'),
			'timeout' : (value.integer,string.nop,'5',           'time before we abandon inactive established connections'),
			'backlog' : (value.integer,string.nop,'200',         'when busy how many connection should the OS queue for us'),
			'listen'  : (value.boolean,string.lower,'true',      'should we listen for connections over IPv4'),
			'out'     : (value.boolean,string.lower,'true',      'allow connections to remote web servers over IPv4'),
			'bind'    : (value.unquote,string.quote,'0.0.0.0',   'which ipv4 to use when creating outbound connection'),
		},
		'tcp6' : {
			'host'    : (value.unquote,string.quote,'::1',   'the host the proxy listen on'),
			'port'    : (value.integer,string.nop,'3128',    'the port the proxy listen on'),
			'timeout' : (value.integer,string.nop,'5',       'time before we abandon inactive established connections'),
			'backlog' : (value.integer,string.nop,'200',     'when busy how many connection should the OS queue for us'),
			'listen'  : (value.boolean,string.lower,'false', 'should we listen for connections over IPv6'),
			'out'     : (value.boolean,string.lower,'true',  'allow connections to remote web servers over IPv6'),
			'bind'    : (value.unquote,string.quote,'::',    'which ipv6 to use when creating outbound connection'),
		},
		'redirector' : {
			'enable'  : (value.boolean,string.lower,'false',                         'use redirector programs to filter http request'),
			'program' : (value.exe,string.path,'etc/exaproxy/redirector/url-allow',  'the program used to know where to send request'),
			'minimum' : (value.integer,string.nop,'5',                               'minimum number of worker threads (forked program)'),
			'maximum' : (value.integer,string.nop,'25',                              'maximum number of worker threads (forked program)'),
			'protocol': (value.redirector,string.quote,'url',                        'what protocol to use (url -> squid like / icap:://<uri> -> icap like)')
		},
		'http' : {
			'idle-connect'    : (value.integer,string.nop,'300',     'time before we abandon new inactive http client connections (0: unlimited)'),
			'connections'     : (value.integer,string.nop,'32768',   'the maximum number of proxy connections'),
			'transparent'     : (value.boolean,string.lower,'false', 'do not reveal the presence of the proxy'),
			'forward'         : (value.lowunquote,string.quote,'',   'read client address from this header (normally x-forwarded-for)'),
			'mask'            : (value.boolean,string.lower,'false', 'hide client address by removing the header specified in exaproxy.http.forward'),
			'connect'         : (value.boolean,string.lower,'true',  'allow client to use CONNECT and https connections'),
			'expect'          : (value.boolean,string.lower,'false', 'block messages with EXPECT headers with a 417'),
			'extensions'      : (value.methods,string.list,'',       'allow new HTTP method (space separated)'),
			'proxied'         : (value.boolean,string.lower,'false', 'request is encapsulated with haproxy proxy protocol'),
			'header-size'     : (value.integer,string.nop,'65536',   'maximum size in bytes for HTTP headers (0 : unlimited)'),
		},
		'passthrough' : {
			'enable'          : (value.boolean,string.lower,'false',             'enable the passthrough server'),
			'host'            : (value.unquote,string.quote,'127.0.0.1',        'the address the passthrough server listens on'),
			'ipv6'            : (value.unquote,string.quote,'::',               'the ipv6 address the passthrough server listens on'),
			'port'            : (value.integer,string.nop,'8000',               'port the passthrough server listens on'),
			'idle-connect'    : (value.integer,string.nop,'300',     'time before we abandon new inactive passthrough client connections (0: unlimited)'),
			'connections'     : (value.integer,string.nop,'32768',   'the maximum number of passthrough connections'),
			'proxied'         : (value.boolean,string.lower,'false', 'request is encapsulated with haproxy proxy protocol'),
		},
		'icap' : {
			'enable'          : (value.boolean,string.lower,'false',             'enable the icap server'),
			'host'            : (value.unquote,string.quote,'127.0.0.1',        'the address the icap server listens on'),
			'ipv6'            : (value.unquote,string.quote,'::',               'the ipv6 address the icap server listens on'),
			'port'            : (value.integer,string.nop,'1344',               'port the icap server listens on'),
			'idle-connect'    : (value.integer,string.nop,'300',     'time before we abandon new inactive icap client connections (0: unlimited)'),
			'connections'     : (value.integer,string.nop,'32768',   'the maximum number of icap connections'),
			'proxied'         : (value.boolean,string.lower,'false', 'request is encapsulated with haproxy proxy protocol'),
			'header-size'     : (value.integer,string.nop,'65536',   'maximum size in bytes for ICAP headers (0 : unlimited)'),
		},
		'tls' : {
			'enable'          : (value.boolean,string.lower,'false',             'enable the TLS server'),
			'host'            : (value.unquote,string.quote,'127.0.0.1',        'the address the TLS server listens on'),
			'ipv6'            : (value.unquote,string.quote,'::',               'the ipv6 address the TLS server listens on'),
			'port'            : (value.integer,string.nop,'443',               'port the TLS server listens on'),
			'idle-connect'    : (value.integer,string.nop,'300',     'time before we abandon new inactive TLS client connections (0: unlimited)'),
			'connections'     : (value.integer,string.nop,'32768',   'the maximum number of TLS connections'),
			'proxied'         : (value.boolean,string.lower,'false', 'request is encapsulated with haproxy proxy protocol'),
			'header-size'     : (value.integer,string.nop,'65536',   'maximum size in bytes for TLS headers (0 : unlimited)'),
		},
		'web' : {
			'enable'      : (value.boolean,string.lower,'true',             'enable the built-in webserver'),
			'host'        : (value.unquote,string.quote,'127.0.0.1',        'the address the web server listens on'),
			'port'        : (value.integer,string.nop,'8080',               'port the web server listens on'),
			'html'        : (value.folder,string.path,'etc/exaproxy/html',  'where internal proxy html pages are served from'),
			'connections' : (value.integer,string.nop,'100',                'the maximum number of web connections'),
			'debug'       : (value.boolean,string.lower,'false',            'allow to debug the program via the web client (do not use in production)'),
		},
		'daemon' : {
			'identifier'  : (value.unquote,string.nop,'ExaProxy','a name for the log (to diferenciate multiple instances more easily)'),
			'pidfile'     : (value.unquote,string.quote,'',      'where to save the pid if we manage it'),
			'user'        : (value.user,string.quote,'nobody',   'user to run as'),
			'daemonize'   : (value.boolean,string.lower,'false', 'should we run in the background'),
			'reactor'     : (value.unquote,string.quote,'best', 'event polling mechanism to use (select/epoll/kqueue/best)'),
			'speed'       : (value.integer,string.nop,'2',       'sleep duration when waiting for connection'),
			'poll-interfaces' : (value.boolean,string.lower,'true',  'periodically poll for local addresses the proxy should not connect to'),
		},
		'security' : {
			'local'       : (value.services,string.services,   '',              'ip:port for allowed services (*:80 or 127.0.0.1:* allowed)'),
			'connect'     : (value.ports,string.list,          '443 981 7000',  'ports allowed with CONNECT'),
		},
		'dns' : {
			'resolver'     : (value.resolver,string.path,'/etc/resolv.conf',       'resolver file'),
			'timeout'      : (value.integer,string.nop,'2',                        'how long to wait for DNS replies before retrying'),
			'retries'      : (value.integer,string.nop,'10',                       'how many times to retry sending requests'),
			'ttl'          : (value.integer,string.nop,'900',                      'amount of time (in seconds) we will cache dns results for'),
			'fqdn'         : (value.boolean,string.lower,'true',                   'only resolve FQDN (hostnames must have a dot'),
			'definitions'  : (value.folder,string.path,'etc/exaproxy/dns/types',   'location of file defining dns query types'),
		},
		'log' : {
			'enable'        : (value.boolean,string.lower,'true',               'enable traffic logging'),
			'level'         : (value.syslog,string.syslog,'ERROR',              'log message with at least the priority logging.<level>'),
			'destination'   : (value.unquote,string.quote,'stdout',             'where syslog should log'),
			'signal'        : (value.boolean,string.lower,'true',               'log messages from the signal subsystem'),
			'configuration' : (value.boolean,string.lower,'true',               'log messages from the configuration subsystem'),
			'supervisor'    : (value.boolean,string.lower,'true',               'log messages from the supervisor subsystem'),
			'daemon'        : (value.boolean,string.lower,'true',               'log messages from the daemon subsystem'),
			'server'        : (value.boolean,string.lower,'true',               'log messages from the server subsystem'),
			'client'        : (value.boolean,string.lower,'true',               'log messages from the client subsystem'),
			'manager'       : (value.boolean,string.lower,'true',               'log messages from the manager subsystem'),
			'worker'        : (value.boolean,string.lower,'true',               'log messages from the worker subsystem'),
			'download'      : (value.boolean,string.lower,'true',               'log messages from the download subsystem'),
			'http'          : (value.boolean,string.lower,'true',               'log messages from the http subsystem'),
			'header'        : (value.boolean,string.lower,'true',               'log messages from the header subsystem'),
			'resolver'      : (value.boolean,string.lower,'true',               'log messages from the dns subsystem'),
			'web'           : (value.boolean,string.lower,'true',               'log messages from the web subsystem'),
		},
		'usage' : {
			'enable'        : (value.boolean,string.lower,'false',              'enable traffic logging'),
			'destination'   : (value.unquote,string.quote,'stdout',              'where syslog should log'),
		},
		'profile' : {
			'enable'      : (value.boolean,string.lower,'false', 'enable profiling'),
			'destination' : (value.unquote,string.quote,'stdout', 'save profiling to file (instead of to the screen on exit)'),
		},
		'proxy' : {
			'version' : (value.nop,string.nop,version,  'ExaProxy\'s version'),
		},
		# Here for internal use
		'debug' : {
			'memory' : (value.boolean,string.lower,'false','command line option --memory'),
			'pdb'    : (value.boolean,string.lower,'false','command line option --pdb'),
			'log'    : (value.boolean,string.lower,'false','command line option --debug'),
		},
	}

	try:
		configuration = load('exaproxy',defaults,arguments['configuration'])
	except ConfigurationError,e:
		print >> sys.stderr, 'configuration issue,', str(e)
		sys.exit(1)