def addProxy(self): transwww = self.sysconf.Shorewall # XXX We should have support for multiple LANPrimary interfaces here. net = [i for j,i in Utils.getLanNetworks(self.sysconf).items()][0] transwww['rules'].append([ 1, "REDIRECT loc 8080 tcp 80 - !%s" % (net) ]) self.sysconf.Shorewall = transwww
def addProxy(self): transwww = self.sysconf.Shorewall net = [i for j, i in Utils.getLanNetworks(self.sysconf).items()][0] if not transwww.get('redirect'): transwww['redirect'] = [] transwww['redirect'].append([ 1, "REDIRECT loc 8080 tcp 80 - !%s" % (net) ]) self.sysconf.Shorewall = transwww
def __init__(self): self.config = confparse.Config() self.lanNetworks = [ i for k, i in Utils.getLanNetworks(self.config).items() ] #self.lanNetwork = '.'.join(self.config.EthernetDevices[self.config.LANPrimary]['ip'].split('.')[:2]) + '.' self.db = Database.AggregatorDatabase() self.portCache = {} # Cache for service lookups self.lastSeen = [] self.sourcesSeen = {} self.itime = 60 # 60 is good self.rtime = 5 * 60 # 5*60 is good reactor.callLater(self.itime, self.persistFlows) print "[NetFlowCollector] Working with LANs: ", self.lanNetworks
def submitRoute(self, ctx, form, data): eth = self.sysconf.EthernetDevices target = None destination = data['dest'].encode("ascii", "replace").lower() if data['gate']: gateway = data['gate'].encode("ascii", "replace") if data['device']: target = data['device'].encode("ascii", "replace") else: gateway = data['device'].encode("ascii", "replace") if '0.0.0.0/0' in destination: destination = 'default' if destination == 'default': # Purge existing default routes, if any for dev, items in eth.items(): oldRoutes = items.get('routes', []) newRoutes = [] for dst, gw in oldRoutes: if dst == "default": continue newRoutes.append((dst, gw)) eth[dev]['routes'] = newRoutes if (not target) and data['gate']: # Dunno where to go... Look at gateway and make an intelligent choice for iface, net in Utils.getLanNetworks(self.sysconf).items(): print data['gate'] if Utils.matchIP(net, gateway): # Gateway matches this interface local-link target = iface if not target: # Still nothing, go for broke - these will be added to Quagga anyways target = Utils.getLans(self.sysconf)[0] routes = eth[target].get('routes', []) routes.append((destination, gateway)) eth[target]['routes'] = routes self.sysconf.EthernetDevices = eth def next(_): return url.root.child('Routing') return applySettings().addCallback(next)
def lanTest(self): def lanScan(res): hosts = {} lastIP = "" ipOrder = [] for i in res.split('\n'): if "Host" in i: if "(" in i: host = i.split()[1] ip = i.split()[2].replace('(', '').replace(')', '') else: ip = i.split()[1] host = ip hosts[ip] = [unicode(host), u"", u""] ipOrder.append(ip) lastIP = ip elif "MAC" in i: mac = i.split()[2] brand = i.split()[3].replace('(', '').replace(')', '') hosts[lastIP][1] = unicode(mac) hosts[lastIP][2] = unicode(brand) bundle = [] for k in ipOrder: v = hosts[k] sortKey = [int(i) for i in k.split('.')] bundle.append((unicode(k), v[0], v[1], v[2])) return bundle loc = [] for k, v in Utils.getLanNetworks(self.sysconf).items(): loc.append('nmap -sP %s 2>&1 | grep -E "(be up|MAC)"' % (v)) return WebUtils.system(';'.join(loc)).addCallback(lanScan)
def submitRoute(self, ctx, form, data): eth = self.sysconf.EthernetDevices target = None destination = data['dest'].encode() if data['gate']: gateway = data['gate'].encode() else: gateway = data['device'].encode() if '0.0.0.0/0' in destination: destination = u'default' if 'eth' in self.sysconf.WANPrimary: target = self.sysconf.WANPrimary else: target = Utils.getLans(self.sysconf)[0] if (not target) and data['gate']: # Dunno where to go... Look at gateway and make an intelligent choice for iface, net in Utils.getLanNetworks(self.sysconf).items(): print data['gate'] if Utils.matchIP(net, gateway): # Gateway matches this interface local-link target = iface if not target: # Still nothing, go for broke target = Utils.getLans(self.sysconf)[0] routes = eth[target].get('routes', []) routes.append((destination, gateway)) eth[target]['routes'] = routes self.sysconf.EthernetDevices = eth def next(_): return url.root.child('Routing') return applySettings().addCallback(next)
def writeConfig(self, *a): path = "/etc/squid/" # Make sure Dansguardian is sorted os.system('mkdir -p /var/log/dansguardian') os.system('touch /var/log/dansguardian/access.log') os.system('chown -R dansguardian:dansguardian /var/log/dansguardian') # Sort out update cache permissions os.system('mkdir -p /var/lib/samba/updates/download') os.system('chown -R proxy:proxy /var/lib/samba/updates') os.system('chmod -R a+rwx /var/lib/samba/updates') os.system('chmod -R a+rwx /usr/local/tcs/tums/uaxeldb') #Fix read permissions for config files os.system('chmod a+r /etc/squid') os.system('chmod a+r /etc/squid/allow_hosts') os.system('chmod a+r /etc/squid/allow_dst') os.system('chmod a+r /etc/squid/allow_domains') allowDest = "" allowHost = "" allowDom = "vulaniblockdomainholder.vulani\n" blockDom = "vulaniblockdomainholder.vulani\n" for h in config.ProxyAllowedDomains: allowDom += "%s\n" % h for h in config.ProxyBlockedDomains: blockDom += "%s\n" % h for h in config.ProxyAllowedDestinations: allowDest += "%s\n" % h for h in config.ProxyAllowedHosts: allowHost += "%s\n" % h l = open(path + 'allow_dst', 'wt') l.write(allowDest) l.close() l = open(path + 'allow_hosts', 'wt') l.write(allowHost) l.close() l = open(path + 'allow_domains', 'wt') l.write(allowDom) l.close() l = open(path + 'denied_domains', 'wt') l.write(blockDom) l.close() adGroupAuth = "" adGroups = [] aclEntries = [ ] #Make sure we don't break the squid config by making reference to undefined acls keep a list of defined acls and only use them if they are in this list if config.ProxyConfig.get('adauth', None): if config.ProxyConfig.get( 'addom', None) and config.ProxyConfig.get( 'adldapuser', None) and config.ProxyConfig.get( 'adldappass', None): basedn = str.join(',', [ "dc=" + str(dfrag) for dfrag in config.ProxyConfig.get( 'addom', str).split('.') ]) adInfo = { 'basedn': basedn, 'ldapuser': config.ProxyConfig['adldapuser'], 'ldappass': config.ProxyConfig['adldappass'], 'adserver': config.ProxyConfig['adserver'] } authentication = "auth_param basic program /usr/lib/squid/ldap_auth -R -b \"%(basedn)s\" -D \"%(ldapuser)s\" -w \"%(ldappass)s\" -f sAMAccountName=%%s -h %(adserver)s -p389" % adInfo if config.ProxyConfig.get('adacls', None): adGroupPaths = [] for adacl in config.ProxyConfig.get('adacls', []): if '=' in adacl[1]: filter = "(memberof=cn=%%a,%s,%s)" % (adacl[1], basedn) if filter not in adGroupPaths: adGroupPaths.append(filter) adGroups.append( "acl vacl_%s external adACLGroup %s" % (adacl[2], adacl[0])) aclEntries.append(adacl[2]) else: print "Invalid AD Group path", adacl[1] if len(adGroupPaths) > 0: if len(adGroupPaths) > 1: adInfo["adGroupFilter"] = "(|%s)" % str.join( "", adGroupPaths) else: adInfo["adGroupFilter"] = adGroupPaths[0] authentication = authentication + "\nexternal_acl_type adACLGroup %%LOGIN /usr/lib/squid/squid_ldap_group -R -b \"%(basedn)s\" -D \"%(ldapuser)s\" -w \"%(ldappass)s\" -f \"(&%(adGroupFilter)s(objectclass=person)(sAMAccountName=%%v))\" -h %(adserver)s -p389" % adInfo else: authentication = "auth_param basic program /usr/lib/squid/msnt_auth" l = open(path + 'msntauth.conf', 'wt') l.write('server %s %s %s\n' % (config.ProxyConfig['adserver'], config.ProxyConfig['adserver'], config.ProxyConfig['addom'])) l.close() os.system('chmod a+r %smsntauth' % path) else: #authentication = "auth_param basic program /usr/libexec/squid/squid_ldap_auth -b "ou=People,%s,o=%s" -f (&(uid=%%s)(employeeType=squid)) localhost #""" % (','.join(["dc=%s"%(i,) for i in config.Domain.split('.')]), config.LDAPBase) authentication = "auth_param basic program /usr/libexec/squid/squid_ldap_auth -b \"o=%s\" -f " % config.LDAPBase # Muchos haxed ldap search authentication += "(&(|(mail=%%s@%s)(mail=%%s))(employeeType=squid)) localhost \n" % config.Domain if config.ProxyConfig.get('contentfilter', None): cfilter = "cache_peer 127.0.0.1 parent 8081 0 no-query login=*:nopassword\n" else: cfilter = "" timeAcls = "" # Do user ACLS here for usrs, aclname in config.ProxyConfig.get('aclusers', []): timeAcls += "acl vacl_%s proxy_auth %s\n" % (aclname, ' '.join( [i.strip() for i in usrs.split(',')])) aclEntries.append(aclname) # Do more destination ACL's here for doms, aclname in config.ProxyConfig.get('domacls', []): timeAcls += "acl vacl_%s dstdomain %s\n" % (aclname, ' '.join( [i.strip() for i in doms.split(',')])) aclEntries.append(aclname) srcacls = "" for i in config.ProxyConfig.get('srcacls', []): src, acl = i if not '/' in src: src_ip = "%s/32" % src else: src_ip = src srcacls += "acl vacl_%s src %s\n" % (acl, src_ip) aclEntries.append(acl) denys = "" allows = "" cnt = 0 if config.ProxyConfig.get('timedaccess', None): for action, days, times, domain, exacl in config.ProxyConfig[ 'timedaccess']: if exacl not in aclEntries: continue cnt += 1 timeAcls += "acl time_acl%s time %s %s\n" % (cnt, days, times) if domain: timeAcls += "acl domain_acl%s dstdomain %s\n" % (cnt, domain) if action: allows += "http_access allow all time_acl%s" % (cnt, ) else: allows += "http_access deny all time_acl%s" % (cnt, ) if domain: allows += " domain_acl%s" % (cnt) if exacl: allows += " vacl_%s" % exacl allows += "\n" bindaddr = "" if config.ProxyConfig.get('bindaddr'): bindaddr = "tcp_outgoing_address %s" % config.ProxyConfig.get( 'bindaddr') routingacls = "" for i in config.ProxyConfig.get('aclgateways', []): gateway, acl = i if acl in aclEntries: routingacls += "tcp_outgoing_address %s vacl_%s\n" % (gateway, acl) for acl, perm in config.ProxyConfig.get('aclperms', []): aclList = [] for e in acl.split(): if e in aclEntries: aclList.append('vacl_' + e) if aclList: if perm == "allow": allows += "http_access allow all %s\n" % str.join( ' ', aclList) else: allows += "http_access deny all %s\n" % str.join( ' ', aclList) # Configure our update accelerator updator = "" redirCache = "" redircacheallow = "" if config.ProxyConfig.get('updates', {}).get('enabled', None): # Allow redir hosts to bypass all Squid auth when we use a captive portal. Also point all to the rewriter if config.ProxyConfig.get('captive'): redirCache = "acl redir_hosts src \"/etc/squid/redir_hosts\"" redircacheallow = "http_access allow redir_hosts" rfi = open('/etc/squid/redir_hosts', 'wt') for iface, net in Utils.getLanNetworks(config).items(): rfi.write(net + '\n') rfi.close() updateConf = config.ProxyConfig['updates'] # Get config options and set some defaults diskspace = updateConf.get('maxspace', 95) speed = updateConf.get('maxspeed', 256) # accelerator.conf accelerator = """#Proxy Settings UPSTREAM_USER= UPSTREAM_PASSWORD= PROXY_PORT=8080 ENABLE_UPDXLRATOR=on UPSTREAM_PROXY= #Accelerator Settings AUTOCHECK_SCHEDULE=daily LOW_DOWNLOAD_PRIORITY=off ENABLE_AUTOCHECK=on PASSIVE_MODE=off FULL_AUTOSYNC=off ENABLE_LOG=on MAX_DISK_USAGE=%s NOT_ACCESSED_LAST=month1 CHILDREN=5 MAX_DOWNLOAD_RATE=%s GREEN_ADDRESS=127.0.0.1\n""" % (diskspace, speed) acc = open('/etc/squid/accelerator.conf', 'wt') acc.write(accelerator) acc.close() # meh os.system('chmod a+r /etc/squid/accelerator.conf') # squid.conf directives updator = "url_rewrite_program /usr/local/tcs/tums/bin/update_cache\n" updator += "url_rewrite_children 20\n" updator += "url_rewrite_access allow redir_cache\n" if config.ProxyConfig.get('captive'): updator += "url_rewrite_access allow redir_hosts\n" updator += "url_rewrite_access deny allow_hosts\n" updator += "url_rewrite_access deny allow_domain\n" updator += "url_rewrite_access deny allow_dst\n" if not config.ProxyConfig.get('captive'): updator += "url_rewrite_access deny all\n" #Allow for someone to specify alternative bound ports asside from the default 8080 #Some installations require explicit binding to port 3128, by no means does this mean #that it should be encouraged ... squidConf_bindPorts = "" if config.ProxyConfig.get('bindports'): bindPorts = str(config.ProxyConfig.get('bindports')) for port in bindPorts.replace(' ', '').split(','): if port == "8080": continue squidConf_bindPorts += "http_port %s transparent\n" % (port) squidconf = """http_port 8080 transparent %(bindPorts)s visible_hostname %(host)s hierarchy_stoplist cgi-bin ? .pl acl QUERY urlpath_regex cgi-bin \\? .pl .asp mail.%(domain)s no_cache deny QUERY cache_mem 32 MB maximum_object_size 1000000 KB cache_dir ufs /var/cache/squid/ 10000 16 256 cache_access_log /var/log/squid/access.log cache_log /var/log/squid/cache.log cache_store_log none pid_filename /var/run/squid.pid #ftp_user [email protected] ignore_expect_100 on hosts_file /etc/hosts %(auth)s auth_param basic children 5 auth_param basic realm Vulani Web Proxy auth_param basic credentialsttl 2 hours refresh_pattern ^ftp: 1440 20%% 10080 refresh_pattern ^gopher: 1440 0%% 1440 refresh_pattern . 0 20%% 4320 refresh_pattern windowsupdate.com/.*\\.(cab|exe) 4320 100%% 43200 reload-into-ims refresh_pattern download.microsoft.com/.*\\.(cab|exe) 4320 100%% 43200 reload-into-ims refresh_pattern akamai.net/.*\\.(cab|exe) 4320 100%% 43200 reload-into-ims strip_query_terms off #acl support.microsoft.com dstdomain support.microsoft.com #reply_header_access Accept-Encoding deny support.microsoft.com #request_header_access Accept-Encoding deny support.microsoft.com acl all src 0.0.0.0/0.0.0.0 acl manager proto cache_object acl localhost src 127.0.0.1/32 acl to_localhost dst 127.0.0.0/8 %(srcacls)s %(adAcls)s acl allow_hosts src "/etc/squid/allow_hosts" acl denied_domains dstdomain "/etc/squid/denied_domains" acl allow_domain dstdomain "/etc/squid/allow_domains" acl allow_dst dst "/etc/squid/allow_dst" acl redir_cache dstdomain .microsoft.com acl redir_cache dstdomain .windowsupdate.com acl redir_cache dstdomain .mirror.ac.za acl redir_cache dstdomain .debian.org acl redir_cache dstdomain .ubuntu.com acl redir_cache dstdomain .avg.com %(redircache)s %(timeacls)s acl password proxy_auth REQUIRED acl SSL_ports port 443 563 acl Safe_ports port 80 # http acl Safe_ports port 21 # ftp acl Safe_ports port 443 563 # https, snews acl Safe_ports port 70 # gopher acl Safe_ports port 210 # wais acl Safe_ports port 1025-65535 # unregistered ports acl Safe_ports port 280 # http-mgmt acl Safe_ports port 488 # gss-http acl Safe_ports port 591 # filemaker acl Safe_ports port 777 # multiling http acl Safe_ports port 901 # SWAT acl purge method PURGE acl CONNECT method CONNECT redirector_access deny localhost http_access allow manager localhost http_access deny manager http_access allow purge localhost http_access deny purge http_access deny !Safe_ports http_access deny CONNECT !SSL_ports http_access deny to_localhost http_access allow all localhost %(allows)s http_access deny denied_domains http_access allow allow_domain http_access allow allow_dst %(denys)s http_access allow allow_hosts %(redircacheallow)s %(passwordAuth)s http_access deny all http_reply_access allow all icp_access allow all cache_mgr postmaster@%(domain)s logfile_rotate 7 append_domain .%(domain)s forwarded_for on cachemgr_passwd %(ldappass)s shutdown cachemgr_passwd %(ldappass)s info stats/objects cachemgr_passwd disable all snmp_access allow localhost coredump_dir /var/log/squid extension_methods REPORT MERGE MKACTIVITY CHECKOUT acl snmpcommunity snmp_community public snmp_port 3401 snmp_access allow snmpcommunity localhost snmp_access deny all\n%(updator)s\n%(bindaddr)s\n%(cfilter)s\n%(routingacls)s""" % { 'redircache': redirCache, 'host': config.Hostname + "." + config.Domain, 'bindPorts': squidConf_bindPorts, 'domain': config.Domain, 'auth': authentication, 'ldappass': config.LDAPPassword, 'timeacls': timeAcls, 'allows': allows, 'denys': denys, 'redircacheallow': redircacheallow, 'updator': updator, 'bindaddr': bindaddr, 'cfilter': cfilter, 'routingacls': routingacls, 'srcacls': srcacls, 'adAcls': str.join('\n', adGroups), 'passwordAuth': len(adGroups) > 0 and config.ProxyConfig.get('adGroupDefaultDeny', False) and ' ' or 'http_access allow all password' } # Apply debian fixes squidconf = squidconf.replace('/usr/libexec/squid/squid_ldap_auth', '/usr/lib/squid/ldap_auth') #squidconf = squidconf.replace('/etc/squid/', '/etc/squid/') os.system('mkdir -p /var/cache/squid > /dev/null 2>&1') os.system('mkdir -p /var/log/squid > /dev/null 2>&1') os.system('chown proxy:proxy /var/cache/squid') os.system('touch /var/log/tums_cache.log') os.system('chown proxy:proxy /var/log/tums_cache.log') os.system('chmod a+rwx /var/log/tums_cache.log') os.system('chown -R proxy:proxy /var/log/squid') os.system('rm -r /var/log/squid3 > /dev/null 2>&1') l = open(path + 'squid.conf', 'wt') l.write(squidconf) l.close() # Configure WPAD script for each LAN range. for ip in Utils.getLanIPs(config): pacfile = """function FindProxyForURL(url, host) { if (shExpMatch(url, "http:*")) return "PROXY %(proxyUrl)s:8080"; if (shExpMatch(url, "https:*")) return "PROXY %(proxyUrl)s:8080"; if (shExpMatch(url, "ftp:*")) return "PROXY %(proxyUrl)s:8080"; return "DIRECT"; }\n""" % { 'proxyUrl': ip } fp = open( '/var/www/localhost/htdocs/wpad-%s.pac' % ip.replace('.', '-'), 'wt') fp.write(pacfile) fp.close() try: default = Utils.getLanIPs(config)[0] os.system( 'cp /var/www/localhost/htdocs/wpad-%s.pac /var/www/localhost/htdocs/wpad.dat' % default.replace('.', '-')) except: pass
def writeConfig(self, *a): # VERY IMPORTANT NOTICE! # # All lines are lead by 8 spaces. These spaces are stripped out at the end. # If you have less than 8 spaces before any new line written to the config # then it will be broken # This is done to make the source semi readable # # END OF IMPORTANT NOTICE # Setup local delivery domains locals = "\n".join(config.LocalDomains) # A list of servers we redeliver or hub mail to serverhosts = ['127.0.0.1'] # Configure hubbed hosts and relay domains relayDoms = config.Mail.get('relay', []) hubs = "" mailReroute = "" for dom, dest in config.Mail.get('hubbed', []): if dest not in serverhosts: serverhosts.append(dest) if "@" in dom: mailReroute += "%s %s byname\n" % (dom,dest) dom = dom.split('@')[-1] else: hubs += "%s %s byname\n" % (dom, dest) if dom not in relayDoms: relayDoms.append(dom) # Branch configuration branches = config.Mail.get('branchtopology', {}) branchMap = {} for r in config.Mail.get('branches', []): # if the items in branches are not lists, we assume an old datastructure if not isinstance(r, list): branchMap[r] = None continue svr, relay = r branchMap[svr] = None if relay: branchMap[svr] = relay.replace(' ', '').replace(';', ',').replace(':', ',').split(',') branchReroute = "" for branch, addrs in branches.items(): for addr in addrs: # Extend relay domains to handle this remote server too dom = addr.split('@')[-1] if dom not in relayDoms: relayDoms.append(dom) if branchMap[branch]: relay = ':'.join(branchMap[branch]) else: relay = branch if relay not in serverhosts: serverhosts.append(relay) # Add the address to mail reroute branchReroute += "%s %s byname\n" % ( addr, relay ) # Setup our relay list relays = "\n".join(relayDoms) # Initialise blacklists blacklistSender = "" blacklistHost = "" blacklistDom = "" for b in config.Mail.get('blacklist', []): if "@" in b: blacklistSender += b + '\n' else: try: int(b.split('.')[0]) blacklistHost += b + '\n' except: blacklistDom += b + '\n' whitelistSender = "" whitelistHost = "" whitelistDom = "" for w in config.Mail.get('whitelist', []): if "@" in w: whitelistSender += w + "\n" else: try: int(w.split('.')[0]) whitelistHost += w + '\n' except: whitelistDom += w + '\n' catchall = "" for c in config.Mail.get('catchall', []): catchall += c + "\n" # System filters copyTo = "#System Filter\nif error_message then finish endif\n\n" if config.Mail.get('copytoall', None): copyTo += "if first_delivery then\n" copyTo += " unseen deliver %s errors_to postmaster@%s\n" % (config.Mail['copytoall'], config.Domain) copyTo += "endif\n\n" for addr, dest in config.Mail.get('copys', []): copyTo += "if $recipients contains %s then\n" % addr copyTo += " unseen deliver %s errors_to postmaster@%s\n" % (dest, config.Domain) copyTo += "endif\n\n" # Global system filter if os.path.exists('/usr/local/tcs/tums/filter.db'): filterCont = open('/usr/local/tcs/tums/filter.db').read() copyTo += filterCont copyTo += "\n" allowsend = "" if config.Mail.get('allowsend', None): allowsend = "\n".join(config.Mail['allowsend']) if config.Mail.get('disableratelimit', None): rateLimit = "" else: rateLimit = """ # System-wide rate limit for dodgey senders defer message = Connection limited: Sender rate $sender_rate / $sender_rate_period. hosts = +relay_hosts !sender_domains = +local_domains : +relay_domains !senders = : ratelimit = 50 / 1h / strict\n""" if config.Mail.get('disablerpfilter', None): senderRpFilter = "" else: senderRpFilter = """ # Block mail from forged address on the local side. deny message = Vulani has rejected this message from $sender_address because it is not local to this site. http://vulani.net/ !sender_domains = +local_domains : +relay_domains !senders = : !senders = +acl_allowed_senders hosts = +relay_hosts !hosts = +server_hosts\n""" Utils.writeConf('/etc/exim4/sender_whitelist', whitelistSender, '#') Utils.writeConf('/etc/exim4/host_whitelist', whitelistHost, '#') Utils.writeConf('/etc/exim4/domain_whitelist', whitelistDom, '#') Utils.writeConf('/etc/exim4/sender_blacklist', blacklistSender, '#') Utils.writeConf('/etc/exim4/host_blacklist', blacklistHost, '#') Utils.writeConf('/etc/exim4/domain_blacklist', blacklistDom, '#') Utils.writeConf('/etc/exim4/allowed_senders', allowsend, '#') Utils.writeConf('/etc/exim4/host_noavscan', "", '#') Utils.writeConf('/etc/exim4/local_domains', locals, '#') Utils.writeConf('/etc/exim4/relay_domains', relays, '#') Utils.writeConf('/etc/exim4/hubbed_hosts', hubs, '#') Utils.writeConf('/etc/exim4/mail_reroute', mailReroute, '#') Utils.writeConf('/etc/exim4/branch_reroute', branchReroute, '#') Utils.writeConf('/etc/exim4/system_filter', copyTo, '#') Utils.writeConf('/etc/exim4/catchall_domains', catchall, '#') # Get rid of the autogenerated tag so aptitude doesn't break us os.system('rm /var/lib/exim4/config.autogenerated > /dev/null 2>&1') systemFilter = "system_filter = /etc/exim4/system_filter\n" if config.Mail.get('noavscan'): avScan = "" avscanacl = "" print "Antivirus scanning disabled!" else: avScan = "av_scanner = clamd:/var/run/clamav/clamd.sock" avscanacl = """ accept condition = ${if <={$message_size}{250k}{yes}{no}} deny message = This message contains a virus ($malware_name) !hosts = +acl_host_noavscan malware = *\n""" primaryDomain = config.Domain hostname = config.ExternalName # Must be externally lookupable(?!?) name mailSize = config.Mail.get('mailsize', '') localNet = " : ".join([v for k,v in Utils.getLanNetworks(config).items()]) for n in Utils.getLanIP6s(config): localNet += ' : %s ' % n.replace(':', '::') # fill in allowed hosts (config.Mail.relay-from) if config.Mail.get('relay-from'): localNet += ' : ' + ' : '.join(config.Mail['relay-from']) extensionBlock = "" # Blocked file extensions if config.Mail.get('blockedfiles', []): extensionBlock = " deny message = We do not accept \".$found_extension\" attachments here.\n" extensionBlock += " demime = %s\n" % ':'.join(config.Mail['blockedfiles']) # Mail rewrite rules rewriteRules = "" for fromm,too,flags in config.Mail.get('rewrites', []): # flags is one of TtFfbcr rewriteRules+=' *@%s $1@%s %s\n' % (fromm, too, flags) # Get any mailman settings mm_router, mm_transport, mm_main = self.MailMan() # SpamAssassin required score spamscore = config.Mail.get('spamscore', 70) # Get greylisting ACLS (if greylisting is enabled) aclCheckSenderGreylist, aclCheckDataGreylist = self.Greylisting() ### Enable tweaked performance performanceTweak = "" if config.Mail.get('performance', False): performanceTweak = " # use muliple directories (default false)\n" performanceTweak += " split_spool_directory\n" performanceTweak += " # queue incoming if load high (no default)\n" performanceTweak += " queue_only_load = 4\n" performanceTweak += " # maximum simultaneous queue runners (default 5)\n" performanceTweak += " queue_run_max = 0\n" performanceTweak += " # parallel delivery of one message to a number of remote hosts (default 2)\n" performanceTweak += " remote_max_parallel = 30\n" performanceTweak += " # simultaneous connections from a single host (default 10)\n" performanceTweak += " smtp_accept_max_per_connection = 20\n" performanceTweak += " # maximum number of waiting SMTP connections (default 20)\n" performanceTweak += " smtp_connect_backlog = 50\n" performanceTweak += " # maximum number of simultaneous incoming SMTP calls that Exim will accept (default 20)\n" performanceTweak += " smtp_accept_max = 0\n" if config.Mail.get('rbls'): RBL = config.Mail.get('rbls') else: RBL = [ "dsn.rfc-ignorant.org/$sender_address_domain", "zen.spamhaus.org", "dnsbl.njabl.org", "bhnc.njabl.org", "combined.njabl.org", "bl.spamcop.net", "psbl-mirror.surriel.com", "blackholes.mail-abuse.org", "dialup.mail-abuse.org" ] ### Exim main configuration eximMain = """ ###################################################################### # MAIN CONFIGURATION SETTINGS # ###################################################################### ldap_default_servers = %(ldap)s primary_hostname = %(hostname)s %(avScan)s spamd_address = 127.0.0.1 783 %(systemFilter)s domainlist local_domains = @ : lsearch;/etc/exim4/local_domains domainlist relay_domains = lsearch;/etc/exim4/relay_domains hostlist relay_hosts = 127.0.0.1 : %(hostlist)s hostlist server_hosts = %(serverhosts)s domainlist acl_domain_whitelist = lsearch;/etc/exim4/domain_whitelist hostlist acl_host_whitelist = net-iplsearch;/etc/exim4/host_whitelist addresslist acl_sender_whitelist = lsearch*@;/etc/exim4/sender_whitelist domainlist acl_domain_blacklist = lsearch;/etc/exim4/domain_blacklist hostlist acl_host_blacklist = net-iplsearch;/etc/exim4/host_blacklist addresslist acl_sender_blacklist = lsearch*@;/etc/exim4/sender_blacklist addresslist acl_allowed_senders = /etc/exim4/allowed_senders hostlist acl_host_noavscan = net-iplsearch;/etc/exim4/host_noavscan acl_smtp_connect = acl_check_host acl_smtp_helo = acl_check_helo acl_smtp_mail = acl_check_sender acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_data acl_smtp_etrn = acl_check_etrn qualify_domain = %(domain)s trusted_users = mail message_size_limit = %(mailSize)s helo_allow_chars = _ host_lookup = * smtp_enforce_sync = false helo_accept_junk_hosts = * strip_excess_angle_brackets strip_trailing_dot delay_warning_condition = "\\ ${if match{$h_precedence:}{(?i)bulk|list|junk}{no}{yes}}" #rfc1413_hosts = ${if eq{$interface_port}{SMTP_PORT} {*}{! *}} rfc1413_query_timeout = 0s sender_unqualified_hosts = %(hostlist)s recipient_unqualified_hosts = %(hostlist)s ignore_bounce_errors_after = 2d timeout_frozen_after = 7d recipients_max = 0 # SSL/TLS cert and key tls_certificate = /etc/exim4/exim.cert tls_privatekey = /etc/exim4/exim.key # Advertise TLS to anyone tls_advertise_hosts = * smtp_etrn_command = /etc/exim4/etrn_script $domain LDAP_AUTH_CHECK_LOGIN = ${lookup ldap { \\ user="******"cn=Manager,o=%(base)s" pass=%(pass)s ldap:///?dn?sub?(&(accountStatus=active)(mail=${quote_ldap:$1}))}}" \\ pass="******" ldap:///?mail?sub?(&(accountStatus=active)(mail=${quote_ldap:$1}))}{yes}{no}} LDAP_AUTH_CHECK_PLAIN = ${lookup ldap { \\ user="******"cn=Manager,o=%(base)s" pass=%(pass)s ldap:///?dn?sub?(&(accountStatus=active)(mail=${quote_ldap:$2}))}}" \\ pass="******" ldap:///?mail?sub?(&(accountStatus=active)(mail=${quote_ldap:$2}))}{yes}{no}} %(extra)s """ % { 'ldap': '127.0.0.1', 'hostname': hostname, 'hostlist': localNet, 'serverhosts': ' : '.join(serverhosts), 'domain': primaryDomain, 'mailSize': mailSize, 'extra': performanceTweak + mm_main, 'systemFilter': systemFilter, 'avScan': avScan, 'base':config.LDAPBase, 'pass':config.LDAPPassword } eximACL=""" ###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### begin acl ###################################################################### # Check connecting host (DNSBL's checked in acl_check_rcpt to ensure no reconnect attempt) ###################################################################### acl_check_host: deny hosts = +acl_host_blacklist accept ###################################################################### # Check conencting host is not pretending to be the localhost ###################################################################### acl_check_helo: accept hosts = +relay_hosts # If the HELO pretend to be this host deny condition = ${if or { \\ {eq {${lc:$sender_helo_name}}{%(hostname)s}} \\ {eq {${lc:$sender_helo_name}}{%(domain)s}} \\ } {true}{false} } accept ###################################################################### # Check sender address ###################################################################### acl_check_sender: deny message = sender envelope address $sender_address is locally blacklisted here. senders = +acl_sender_blacklist accept ###################################################################### # Check incoming messages ###################################################################### acl_check_rcpt: # Accept if source is local SMTP accept hosts = : # Deny if illegal characters in email address deny local_parts = ^.*[@%%!/|] : ^\\\\. %(ratelimit)s # Accept mail to postmaster at any local domain without any checks accept local_parts = postmaster domains = +local_domains %(senderRpFilter)s # Accept local, authenticated, whitelisted and dnswl'd hosts accept hosts = +relay_hosts accept authenticated = * accept dnslists = list.dnswl.org accept hosts = +acl_host_whitelist accept domains = +acl_domain_whitelist accept senders = +acl_sender_whitelist # Deny if domain is locally blacklisted deny message = rejected because $sender_domain is locally blacklisted here domains = +acl_domain_blacklist # Deny if listed in a DNSBL deny message = rejected because $sender_host_address is in a blacklist \\ at $dnslist_domain\\n$dnslist_text !senders = : domains = +local_domains : +relay_domains dnslists = %(rbl)s # Accept if this is a local domain accept domains = +local_domains endpass message = unknown user verify = recipient # Accept if this is a relay domain accept domains = +relay_domains endpass message = unrouteable address verify = recipient %(senderGreylist)s # Deny everything else deny message = relay not permitted ###################################################################### # Check contents of email ###################################################################### acl_check_data: %(dataGreylist)s # ClamAV virus scanning deny message = Vulani has rejected this message because it contains a virus: ($malware_name) http://vulani.net log_message = rejected VIRUS ($malware_name) from $sender_address to $recipients !hosts = +acl_host_noavscan demime = * malware = */defer_ok # Reject messages that have serious MIME errors. This calls the demime # condition again, but will return cached results. deny message = Vulani has rejected this message because it contains a broken MIME container ($demime_reason) http://vulani.net log_message = rejected broken MIME container ($demime_reason) from $sender_address to $recipients condition = ${if >{$demime_errorlevel}{2}{1}{0}} demime = * # SpamAssassin Content Filtering # Include Spam Score in Header warn message = X-Spam-Score: $spam_score\\n\\ X-Spam-Score-Int: $spam_score_int\\n\\ X-Spam-Bar: $spam_bar condition = ${if <{$message_size}{250k}{1}{0}} !hosts = +relay_hosts spam = nobody:true/defer_ok # Reject spam messages with score over 7, using an extra condition. deny message = Vulani has rejected this message because it scored $spam_score spam points and is considered to be unsolicited http://vulani.net log_message = rejected SPAM score above threshhold in message from $sender_address to $recipients !hosts = +acl_host_noavscan condition = ${if >{$spam_score_int}{70}{1}{0}} spam = nobody:true %(extblock)s accept ###################################################################### # Check ETRN requests ###################################################################### acl_check_etrn: accept hosts = 0.0.0.0/0 """ % { 'rbl': ' : '.join(RBL), # DNS block lists 'spamlow': int(spamscore)-20, # Warn spam score 'spamhigh': int(spamscore), # Drop spam score. 'senderGreylist': aclCheckSenderGreylist, # Greylisting configuration 'dataGreylist': aclCheckDataGreylist, # 'extblock': extensionBlock, # Blocked file extensions 'hostname': hostname, 'domain': primaryDomain, 'senderRpFilter': senderRpFilter, 'ratelimit': rateLimit, 'avscan': avscanacl } # Trigger our disclaimer transport if config.Mail.get('disclaimer'): transport = "remote_smtp_filter" else: transport = "remote_smtp" # Set the external router depending on how the relay is set if config.SMTPRelay: externalRouter = """ gateway: driver = manualroute domains = ! +local_domains route_list = * %s bydns transport = %s """ % (config.SMTPRelay, transport) else: externalRouter = """ dnslookup: driver = dnslookup domains = ! +local_domains transport = %s ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more """ % transport eximRouters = """ ###################################################################### # ROUTERS CONFIGURATION # ###################################################################### begin routers etrn_already: driver = accept transport = bsmtp_for_etrn require_files = /var/spool/mail/etrn/$domain domains = lsearch;/etc/exim/etrn_domains etrn_delay: driver = accept transport = bsmtp_for_etrn condition = ${if >{$message_age}{1800} {yes}{no}} domains = lsearch;/etc/exim/etrn_domains mail_reroute: driver = manualroute route_data = ${lookup{$local_part@$domain}lsearch{/etc/exim4/mail_reroute}} transport = remote_smtp branch_reroute: driver = manualroute route_data = ${lookup{$local_part@$domain}lsearch{/etc/exim4/branch_reroute}} transport = remote_smtp hubbed_hosts: driver = manualroute domains = ! +local_domains route_data = ${lookup{$domain}lsearch{/etc/exim/hubbed_hosts}} transport = remote_smtp %(extro)s userforward: driver = redirect domains = +local_domains file = /var/spool/mail/forward/${local_part}@${domain} no_verify no_expn check_ancestor file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply alias_user_vacation: driver = redirect domains = +local_domains allow_defer allow_fail data = ${lookup ldap {user="******" pass=%(ldappass)s \\ ldap:///?mail?sub?(mailAlternateAddress=${local_part}@${domain})}} redirect_router = user_vacation retry_use_local_part user_vacation: driver = accept domains = +local_domains require_files = /var/spool/mail/vacation/${local_part}@${domain}.txt no_verify user = apache senders = !^.*-request@.* : !^owner-.*@.* : !^postmaster@.* : \\ ! ^listmaster@.* : !^mailer-daemon@.* : !^noreply@.* : \\ !^.*-bounces@.* transport = vacation_reply unseen ldap_aliases: driver = redirect domains = +local_domains allow_defer allow_fail data = ${lookup ldap {user="******" pass=%(ldappass)s \\ ldap:///?mail?sub?(mailAlternateAddress=${local_part}@${domain})}} redirect_router = ldap_forward retry_use_local_part ldap_forward: driver = redirect domains = +local_domains allow_defer allow_fail data = ${lookup ldap {user="******" pass=%(ldappass)s \\ ldap:///?mailForwardingAddress?sub?\\ (&(accountStatus=active)(mail=${local_part}@${domain}))}{$value}fail} no_expn retry_use_local_part no_verify ldap_user: driver = accept domains = +local_domains condition = ${if eq {}{${lookup ldap {user="******" pass=%(ldappass)s \\ ldap:///?mail?sub?(&(accountStatus=active)(mail=${local_part}@${domain}))}}}{no}{yes}} group = users retry_use_local_part transport = local_delivery catchall: domains = lsearch;/etc/exim/catchall_domains driver = redirect data = catchall@${domain} %(router)s #localuser: # driver = accept # domains = +local_domains # check_local_user # transport = local_delivery """ % { 'router': mm_router, 'ldapbase': config.LDAPBase, 'ldappass': config.LDAPPassword, 'extro': externalRouter, } ## Prevent bounce of failed hosts? (Maximum send timeout reached) hostfailBounce = "" if config.Mail.get('hostfailbounce', False): hostfailBounce += " delay_after_cutoff = false\n" if config.Mail.get('smtpinterface'): hostfailBounce += " interface = %s\n" % config.Mail.get('smtpinterface') eximTransports = """ ###################################################################### # TRANSPORTS CONFIGURATION # ###################################################################### begin transports bsmtp_for_etrn: driver=appendfile file=/var/spool/mail/etrn/$domain user=mail batch_max=1000 use_bsmtp vacation_reply: debug_print = "T: vacation_reply for $local_part@$domain" driver = autoreply file = /var/spool/mail/vacation/${local_part}@${domain}.txt file_expand log = /var/spool/mail/vacation/${local_part}@${domain}.log once_repeat = 7d once = /var/spool/mail/vacation/${local_part}@${domain}.db from = ${local_part}@${domain} to = $sender_address subject = "Re: $h_subject" text = "\\ This is an automated response for $local_part@${domain}:\\n\\ ====================================================\\n\\n" remote_smtp: driver = smtp %(iface)s remote_smtp_filter: driver = smtp transport_filter = /usr/local/tcs/tums/bin/remime %(iface)s local_delivery: driver = appendfile create_directory delivery_date_add directory = ${lookup ldap {user="******" pass=%(wpass)s \\ ldap:///?mailMessageStore?sub?(&(accountStatus=active)\\ (mail=${local_part}@${domain}))}} directory_mode = 770 envelope_to_add group = mail maildir_format mode = 660 return_path_add user = mail address_pipe: driver = pipe return_output address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add address_reply: driver = autoreply %(mm)s\n""" % { 'iface': hostfailBounce, 'basedn': config.LDAPBase, 'wpass': config.LDAPPassword, 'mm': mm_transport } eximOther = """ ###################################################################### # RETRY CONFIGURATION # ###################################################################### begin retry * * senders=: F,2m,1m * * F,2h,15m; G,16h,1h,1.5; F,7d,4h ###################################################################### # REWRITE CONFIGURATION # ###################################################################### begin rewrite %(rewrite)s ###################################################################### # AUTHENTICATION CONFIGURATION # ###################################################################### begin authenticators login: driver = plaintext public_name = LOGIN server_prompts = "Username:: : Password::" server_advertise_condition = yes server_condition = ${if match_ip{$sender_host_address}{+relay_hosts}{yes}{LDAP_AUTH_CHECK_LOGIN}} server_set_id = $1 plain: driver = plaintext public_name = PLAIN server_prompts = : server_advertise_condition = yes server_condition = ${if match_ip{$sender_host_address}{+relay_hosts}{yes}{LDAP_AUTH_CHECK_PLAIN}} server_set_id = $2 """ % { 'base':config.LDAPBase, 'pass':config.LDAPPassword, 'rewrite': rewriteRules } confFile = eximMain + eximACL + eximRouters + eximTransports + eximOther os.system('mkdir -p /var/spool/mail/forward/') os.system('mkdir -p /var/spool/mail/etrn/') # Reprocess the config file lp = confFile.split('\n') confFile = "" for i in lp: confFile += i[8:] + '\n' confFile = confFile.replace('/etc/exim/', '/etc/exim4/').replace('apache', 'www-data') # Patches user names confFile = confFile.replace('user=mail', 'user=Debian-exim') Utils.writeConf('/etc/exim4/exim4.conf', confFile, '#') os.system('chmod a+r /etc/exim4/*') os.system('chmod -R a+r /usr/local/tcs/tums/data') os.system('chmod a+x /etc/exim4/etrn_script >/dev/null 2>&1') os.system('chmod a+rx /var/mail/vacation >/dev/null 2>&1') os.system('chown Debian-exim:Debian-exim /var/spool/mail/etrn') os.system('mkdir /var/cache/vulani/ >/dev/null 2>&1') ### Mailname mailname = "%s.%s\n" % ( config.Hostname, config.Domain ) l = open('/etc/mailname', 'wt') l.write(mailname) l.close()
def writeConfig(self, *a): lans = Utils.getLanNetworks(config) extramain = config.DHCP.get('main','') ips = Utils.getLanIPs(config) myIp = ips[0] rev = '.'.join([i for i in reversed(myIp.split('.')[:3])]) ifaces = [] dhcpconf = """# DHCPD config generated by TUMS Configurator ddns-update-style interim; default-lease-time 21600; max-lease-time 21600; allow booting; allow bootp; authoritative; log-facility local7; zone %(domain)s. { primary 127.0.0.1; } zone %(rev)s.in-addr.arpa. { primary 127.0.0.1; } option local-pac-server code 252 = text; %(extramain)s """ % { 'extramain': extramain, 'domain': config.Domain, 'rev': rev } n = 0 for k,v in lans.items(): myNet = v myIp = config.EthernetDevices[k].get('ip', '/').split('/')[0] dhcpConf = config.DHCP.get(k, {}) if not myIp: # No IP set for this interface (is DHCP itself) continue if not config.EthernetDevices[k].get('dhcpserver'): # Not set to do DHCP continue ifaces.append(k) statics = "" for ip, hostmac in config.DHCP.get('leases',{}).items(): if Utils.matchIP(myNet, ip): # make sure the IP is in this network host, mac = hostmac statics += """ host %s { fixed-address %s; hardware ethernet %s; }\n""" % (host, ip, mac) myNetmask = Utils.cidr2netmask(myNet.split('/')[1]) rangeStart = dhcpConf.get('rangeStart', "100") rangeEnd = dhcpConf.get('rangeEnd', "240") netmask = dhcpConf.get('netmask', myNetmask) netbios = dhcpConf.get('netbios', myIp) nameserver = dhcpConf.get('nameserver', myIp) router = dhcpConf.get('gateway', myIp) myNet = dhcpConf.get('network', Utils.getNetwork(config.EthernetDevices[k]['ip'])) domain = dhcpConf.get('domain', config.Domain) if not '/' in myNet: # AAAAAAAAAAAARGH GOD DAMN DIE IN HELL PAUL VIXIE cdr = Utils.netmask2cidr(netmask) myNet = "%s/%s" % (myNet, cdr) bcast = Utils.getBroadcast(myNet) else: bcast = Utils.getBroadcast(myNet) # allow custom configuration options custom = dhcpConf.get('custom', '') netL = '.'.join(myNet.split('.')[:3]) if not ("." in rangeStart): rangeStart = "%s.%s" % (netL, rangeStart) rangeEnd = "%s.%s" % (netL, rangeEnd) defn = { 'netname': 'DHCP%s' % k.upper(), 'myIp': myIp, 'pacIp': myIp.replace('.', '-'), 'domain': domain, 'network': netL, 'networkF': myNet.split('/')[0], 'static': statics, 'custom': custom, 'netmask': netmask, 'rangeStart': rangeStart, 'rangeEnd': rangeEnd, 'myNetbios': netbios, 'myDns': nameserver, 'myRouter': router, 'extramain': extramain, 'bcast': bcast } dhcpnet = """ shared-network %(netname)s { use-host-decl-names on; option domain-name "%(domain)s"; option domain-name-servers %(myDns)s; option netbios-name-servers %(myNetbios)s; option netbios-node-type 8; option local-pac-server "http://%(myIp)s/wpad-%(pacIp)s.pac"; option ntp-servers %(myIp)s; option time-servers %(myIp)s; option log-servers %(myIp)s; option font-servers %(myIp)s; option pop-server %(myIp)s; option smtp-server %(myIp)s; option x-display-manager %(myIp)s; subnet %(networkF)s netmask %(netmask)s { range dynamic-bootp %(rangeStart)s %(rangeEnd)s; option subnet-mask %(netmask)s; option broadcast-address %(bcast)s; option routers %(myRouter)s; } %(static)s %(custom)s }\n""" % defn dhcpconf += dhcpnet # Check for debianism (goes in /etc/dhcp3) f = open('/etc/dhcp3/dhcpd.conf', 'wt') f.write(dhcpconf) f.close() f = open('/etc/default/dhcp3-server', 'wt') f.write('# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?\n') f.write('# Separate multiple interfaces with spaces, e.g. "eth0 eth1".\n') f.write('INTERFACES="%s"\n' % ' '.join(ifaces)) f.close()