def generateConf(node): confstr_list = ["""\ ! auto-generated by pmacctd NetFlow9 service (monitoring.py) !pidfile: /var/run/pmacctd_nf9.pid daemonize: true """] for intf in node.netifs(): confstr_list.extend(['interface: ', intf.name, '\n']) confstr_list.append( """ !aggregate: src_host, dst_host, src_port, dst_port, proto, tos plugins: nfprobe """) # add any nfprobe9sink which is on our AS to the list of collectors service_helpers.nodewalker(node, node, confstr_list, NetFlow9ProbeServicePMAcct.nodewalker_callback) confstr_list.append( """ nfprobe_version: 9 nfprobe_timeouts: tcp=120:tcp.rst=4:tcp.fin=10:udp=10:icmp=10:general=120:expint=3:maxlife=3600 """) return ''.join(confstr_list)
def generateHostsIf(node, verbose=False): confstr_list = [] if not verbose: service_helpers.nodewalker(node, node, confstr_list, ICMPProbeService.nodewalker_if_callback) else: service_helpers.nodewalker(node, node, confstr_list, ICMPProbeService.nodewalker_if_verbose_callback) return ''.join(confstr_list)
def generateDBAuthoritativeFile(cls, node, zone, nameservers_cb, delegation_servers_cb=None, hosts_cb=None): servers, zone_servers = cls.getServers(cls, node, zone, nameservers_cb) tmpservers = [] for server, addr, server_zone in servers: if server_zone == '.': tmpservers.append(('%s.' % server, addr, server_zone)) else: tmpservers.append(('%s.%s' % (server, server_zone), addr, server_zone)) servers = tmpservers if zone == '.': zone_servers = [('%s.' % server, addr) for server, addr in zone_servers] else: zone_servers = [('%s.%s' % (server, zone), addr) for server, addr in zone_servers] #print(('[==DEBUG==] servers: %s' % servers)) #print(('[==DEBUG==] zone_servers: %s' % zone_servers)) rawzonecontents = cls.compileZoneFile(cls, list([(x[0], x[1], zone) for x in zone_servers]))[0] #print(('[DEBUG] generateDBAuthoritativeFile(node="%s", zone="%s"): zone_servers: %s' % # (node, zone, zone_servers))) SOAHeader = cls.generateSOAHeader(cls, zone_servers, zone) #print(('[DEBUG] SOAHeader: %s' % SOAHeader)) zonecontents = '%s\n%s' % (SOAHeader, rawzonecontents) #print(('[DEBUG] zonecontents: %s' % zonecontents)) if not delegation_servers_cb is None: delegation_servers = [] service_helpers.nodewalker(node, node, delegation_servers, delegation_servers_cb) delegation_servers_map = {} for server, addr, server_zone in delegation_servers: if server_zone == '.': servername = ('%s.' % server) else: servername = ('%s.%s' % (server, server_zone)) if not server_zone in delegation_servers_map: delegation_servers_map[server_zone] = [] delegation_servers_map[server_zone].append((servername, addr)) delegation_records = [] for server_zone, servers in delegation_servers_map.items(): delegation_records.append(cls.generateDelegationRecord(cls, servers, server_zone)) zonecontents = '%s\n%s' % (zonecontents, '\n\n'.join(delegation_records)) if not hosts_cb is None: hosts = [] service_helpers.nodewalker(node, node, hosts, hosts_cb) # remove nameservers as they have already been added # TODO: remove nameservers as they have already been added -- hosts = [(server_name, v6addr, zone) for server_name, v6addr, zone ] host_records = cls.compileZoneFile(cls, None, hosts)[1] #print(('[DDEBUGG] host_records: %s' % str(host_records))) zonecontents = '%s\n%s' % (zonecontents, host_records) if len(servers) > 0: cls.writeZoneFile(cls, node, zone, zonecontents)
def getServers(cls, node, zone, nodewalker_cb): # add any authoritative dns server to the list of resolvers for that AS, # if we are not an authoritative dns server for the same AS servers = [] service_helpers.nodewalker(node, node, servers, nodewalker_cb) # servers managing virtual zone zone_servers = [] for servername, ipaddr, server_zone in servers: #print(('[DEBUG] candidate: server: %s, zone: %s' % (servername, server_zone))) if server_zone == zone: #print(('[DEBUG] adding to zone: "%s" server: "%s" (%s)' % # (server_zone, servername, ipaddr))) zone_servers.append((servername, ipaddr)) return servers, zone_servers
def generateResolvconf(cls, node, services): confstr_list = [] if service_flags.DNSResolver in node.services: # if we are a DNS server, add ::1, 127.0.0.1 to resolv.conf if node.enable_ipv6: confstr_list.append('nameserver ::1\n') if node.enable_ipv4: confstr_list.append('nameserver 127.0.0.1\n') else: print('[DNSResolvconf] generating for node: %s' % node.name) # add any dns server which is on our AS to the list of resolvers list_len = len(confstr_list) service_helpers.nodewalker(node, node, confstr_list, cls.nodewalker_Resolver_only_callback) print('[DNSResolvconf] found %d resolvers' % len(confstr_list)) # if no resolvers could be found, also include authoritative AS dns if list_len == len(confstr_list): list_len = len(confstr_list) service_helpers.nodewalker(node, node, confstr_list, cls.nodewalker_Resolver_and_ASAuth_only_callback) print('[DNSResolvconf] found %d resolvers and AS auth servers' % len(confstr_list)) # if no resolvers could be found, also include authoritative AS and root dns if list_len == len(confstr_list): service_helpers.nodewalker(node, node, confstr_list, cls.nodewalker_all_DNS_Resolver_callback) print('[DNSResolvconf] found %d resolvers, AS auth and root servers' % len(confstr_list)) confstr_list.append('search virtual\ndomain virtual\n') return ''.join(confstr_list)
def getAndGeneratePTRZonesASAuthServer(cls, node): """ returns a list of all reverse zones a root dns server serves """ # find dns as authoritative servers # (server_name, server_addr, zone) as_auth_servers = [] service_helpers.nodewalker(node, node, as_auth_servers, cls.nodewalker_root_dns_find_all_auth_servers_callback) as_auth_servers = [('%s.%s' % (server_name, zone), server_addr, zone) \ for server_name, server_addr, zone in as_auth_servers] # zone = "AS%s.virtual." % str(netid) zonenames = [] if hasattr(node, 'netid') and not node.netid is None: netid = node.netid else: # TODO: netid 0 is invalid netid = 0 asn = netid for ipversion in node.getIPversions(): # collect loopback address space loopback_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, netid, ipversion) print(('[DEBUG] loopback_net IPv%d: %s' % (ipversion, loopback_net))) # collect interface address space interface_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, netid, ipversion) print(('[DEBUG] interface_net IPv%d: %s' % (ipversion, interface_net))) if ipversion == 4: auth_servers = [(server_name, server_addr) \ for server_name, server_addr, zone in as_auth_servers \ if zone == "AS%s.virtual." % str(netid) and \ isIPv4Address(server_addr)] elif ipversion == 6: auth_servers = [(server_name, server_addr) \ for server_name, server_addr, zone in as_auth_servers \ if zone == "AS%s.virtual." % str(netid) and \ isIPv6Address(server_addr)] else: raise ValueError for asn_net in loopback_net, interface_net: zonename = cls.getPTRZoneNameFromPrefix(cls, asn_net) print(('[DEBUG] zonename: %s' % zonename)) ORIGINHeader = '$ORIGIN %s\n' % zonename print(('[DEBUG] ORIGINHeader: %s' % ORIGINHeader)) SOAHeader = cls.generateSOAHeader(cls, auth_servers, zonename) print(('[DEBUG] SOAHeader:\n%s' % SOAHeader)) zoneentries = [] # get host list of this AS # TODO: iterating over all nodes for interface and # loopback address space is expensive. and we are only talking # about IPv4 or IPv6 at the moment. # is there a better way of doing this? hosts = [] service_helpers.nodewalker(node, node, hosts, cls.nodewalker_asroot_dns_find_hosts_in_as_callback) for hostname, asn_addr, zone in hosts: if ipversion == 4 and not isIPv4Address(asn_addr): continue if ipversion == 6 and not isIPv6Address(asn_addr): continue if ipversion == 4: asn_addr = IPv4Addr(asn_addr) elif ipversion == 6: asn_addr = IPv6Addr(asn_addr) else: raise ValueError if asn_addr < asn_net.minaddr() or \ asn_addr > asn_net.maxaddr(): continue # set prefix length. just to be sure asn_addr.set_prefixlen(asn_net.prefixlen) asn_ptr_name = cls.getPTR_CNAME_FromAddr(cls, asn_addr) print(('[DEBUG] ASN PTR addr (IPv%d): %s' % (ipversion, str(asn_addr)))) print(('[DEBUG] adding: "%s IN PTR %s.AS%s.virtual.' % (asn_ptr_name, hostname, str(netid)))) zoneentries.append(('%s IN PTR %s.AS%s.virtual.' % (asn_ptr_name, hostname, str(netid)))) print(('[DEBUG] PTR records: %s' % (zoneentries))) zonecontents = '%s\n%s\n%s\n' % (ORIGINHeader, SOAHeader, '\n'.join(zoneentries)) cls.writeZoneFile(cls, node, zonename, zonecontents) print(('[DEBUG] adding ptrzone: %s' % zonename)) zonenames.append(zonename) return zonenames
def getAndGeneratePTRZonesRootServer(cls, node): """ returns a list of all reverse zones a root dns server serves """ # find dns root servers # (server_name, server_addr) rootservers = [] service_helpers.nodewalker(node, node, rootservers, cls.nodewalker_find_root_dns_callback) rootservers = [('%s.' % server_name, server_addr) \ for server_name, server_addr in rootservers] # find dns as authoritative servers # (server_name, server_addr, zone) as_auth_servers = [] service_helpers.nodewalker(node, node, as_auth_servers, cls.nodewalker_root_dns_find_all_auth_servers_callback) as_auth_servers = [('%s.%s' % (server_name, zone), server_addr, zone) \ for server_name, server_addr, zone in as_auth_servers] zonenames = [] SOAHeader = cls.generateSOAHeader(cls, rootservers, '.') print(('[DEBUG] SOAHeader:\n%s' % SOAHeader)) for ipversion in node.getIPversions(): # collect loopback address space loopback_net = Loopback.getLoopbackNet(ipversion) print(('[DEBUG] loopback_net IPv%d: %s' % (ipversion, loopback_net))) # collect interface address space interface_net = Interface.getInterfaceNet(ipversion) print(('[DEBUG] interface_net IPv%d: %s' % (ipversion, interface_net))) # get all deployed ASN's asns = list(NetIDNodeMap.mapping[node.session.sessionid].keys()) print(('[DEBUG] deployed ASN\'s: %s' % asns)) for net in loopback_net, interface_net: zonename = cls.getPTRZoneNameFromPrefix(cls, net) net_prefixlen = net.prefixlen print(('[DEBUG] zonename: %s' % zonename)) ORIGINHeader = '$ORIGIN %s\n' % zonename print(('[DEBUG] ORIGINHeader: %s' % ORIGINHeader)) zoneentries = [] for asn in asns: # get AS address space if net == loopback_net: asn_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, asn, ipversion) elif net == interface_net: asn_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, asn, ipversion) # find authoritative AS dns servers # zone == "AS%s.virtual." % str(netid) for server_name, server_addr, zone in as_auth_servers: server_asn = zone.lstrip('AS') server_asn = int(server_asn[:server_asn.find('.')]) # not the correct asn if not asn == server_asn: continue # not our IP version if ipversion == 4 and not isIPv4Address(server_addr): continue if ipversion == 6 and not isIPv6Address(server_addr): continue print(('[DEBUG] server_name: %s, server_addr: %s, zone: %s' % (server_name, server_addr, zone))) if ipversion == 4: # get host list of this AS # TODO: iterating over all nodes for each AS for interface and # loopback address space is expensive. and we are only talking # about IPv4 at the moment. is there a better way of doing this? hosts = [] # TODO: tmp. setting another netid of a node is a dirty hack tmpnetid = node.netid node.netid = server_asn service_helpers.nodewalker(node, node, hosts, cls.nodewalker_asroot_dns_find_hosts_in_as_callback) node.netid = tmpnetid for hostname, asn_addr, zone in hosts: if not isIPv4Address(asn_addr): continue asn_addr = IPv4Addr(asn_addr) print(('[DEBUG] asn_addr(%s) in asn_net(%s)' % (str(asn_addr), str(asn_net)))) if asn_addr < asn_net.minaddr() or \ asn_addr > asn_net.maxaddr(): continue # set prefix length of the supernet asn_addr.set_prefixlen(net_prefixlen) asn_ptr_name = cls.getPTR_CNAME_FromAddr(cls, asn_addr) #print(('[DEBUG] deployed ASN network (IPv%d): %s' % # (ipversion, str(asn_net)))) print(('[DEBUG] ASN PTR addr (IPv%d): %s' % (ipversion, str(asn_addr)))) print(('[DEBUG] adding: "%s IN NS %s"' % (asn_ptr_name, server_name))) zoneentries.append(('%s IN NS %s' % (asn_ptr_name, server_name))) elif ipversion == 6: asn_ptr_name = cls.getPTRZoneNameFromPrefix(cls, asn_net) print(('[DEBUG] adding: "%s IN NS %s"' % (asn_ptr_name, server_name))) zoneentries.append(('%s IN NS %s' % (asn_ptr_name, server_name))) print(('[DEBUG] subnet name servers: %s' % (zoneentries))) zonecontents = '%s\n%s\n%s\n' % (ORIGINHeader, SOAHeader, '\n'.join(zoneentries)) cls.writeZoneFile(cls, node, zonename, zonecontents) print(('[DEBUG] adding ptrzone to zonenames: %s' % zonename)) zonenames.append(zonename) return zonenames
def generatequaggaconfig(cls, node): v6cfg = [] v6prefixes = [] if not node.enable_ipv4 and not node.enable_ipv6: return '' cfg = '!\n! BGP configuration\n!\n' cfg += 'log file /tmp/quagga-bgp-%s.log\n' % node.name cfg += 'router bgp %s\n' % node.netid cfg += ' bgp router-id %s\n' % cls.routerid(node) cfg += ' redistribute kernel\n' cfg += ' redistribute static\n' cfg += '!\n' if hasattr(node, 'netid') and not node.netid is None: netid = node.netid else: # TODO: netid 0 is invalid netid = 0 # configure EBGP connections: if service_flags.EGP in node.services: tmpcfg, tmpv6cfg = cls.configure_EGP(node) cfg += tmpcfg v6cfg.extend(tmpv6cfg) # configure IBGP connections confstr_list = [cfg] # full mesh service_helpers.nodewalker(node, node, confstr_list, cls.nodewalker_ibgp_find_neighbors_callback) cfg = ''.join(confstr_list) if node.enable_ipv4 and service_flags.EGP in node.services: interface_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, netid, 4) loopback_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, netid, 4) cfg += ' network %s\n' % str(loopback_net) cfg += ' network %s\n' % str(interface_net) cfg += ' aggregate-address %s summary-only\n' % str(loopback_net) cfg += ' aggregate-address %s summary-only\n' % str(interface_net) if node.enable_ipv6: v6_ibgp_neighbor_list = [] service_helpers.nodewalker(node, node, v6_ibgp_neighbor_list, cls.nodewalker_ibgp_find_neighbor_addrs_v6_callback) cfg += ' address-family ipv6\n' # activate IBGP neighbors cfg += ''.join([(' neighbor %s activate\n') % \ (str(remote_addr).split('/')[0]) \ for local_addr, remote_addr in v6_ibgp_neighbor_list]) # activate EBGP neighbors cfg += ''.join(v6cfg) if service_flags.EGP in node.services: # announce networks interface_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, netid, 6) loopback_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, netid, 6) cfg += ' network %s\n' % str(loopback_net) cfg += ' network %s\n' % str(interface_net) cfg += ' aggregate-address %s summary-only\n' % str(loopback_net) cfg += ' aggregate-address %s summary-only\n' % str(interface_net) adj_addrs = cls.collect_adjacent_loopback_addrs_v6(cls, node) for adj_addr in adj_addrs: cfg += ' network %s/128\n' % str(adj_addr) cfg += '\n exit-address-family\n' return cfg
def generateHosts(node): confstr_list = [] service_helpers.nodewalker(node, node, confstr_list, DNSProbeService.nodewalker_callback) return ''.join(confstr_list)
def generateStartScript(cls, node): """ enable Netflow probe on peering links """ config_list = [] if not service_flags.EGP in node.services: config_list.append('# this is no border-router. disabling Netflow\n') return ''.join(config_list) config_list.extend([ '#!/bin/sh\n', '# auto-generated by %s service (monitoring.py)\n\n' % cls._name ]) base_sflowd_argv = ['/usr/local/sbin/softflowd'] if node.enable_ipv6: # monitor IPv6 base_sflowd_argv.append(' -6') # export NetFlow9 base_sflowd_argv.append(' -v9') # transport layer protocol for exporting packets: UDP base_sflowd_argv.append(' -Pudp') # Set flow tracking level (default: full) base_sflowd_argv.append(' -Tfull') # Track up to 65536 flows base_sflowd_argv.append(' -m65536 ') # flow timeout definitions base_sflowd_argv.append((' -ttcp=120 -ttcp.rst=4 -ttcp.fin=10' ' -tudp=10 -ticmp=10 -tgeneral=120 -tmaxlife=600')) # check every three seconds for expired flows base_sflowd_argv.append(' -texpint=3') # add any nfprobe9sink which is on our AS to the list of collectors collectors = [] service_helpers.nodewalker(node, node, collectors, NetFlow9ProbeServiceSoftflowd.nodewalker_callback) for collector in collectors: base_sflowd_argv.append(' -n %s:2055' % collector) for localnetif in node.netifs(): # do not ever include control interfaces in anything if hasattr(localnetif, 'control') and localnetif.control == True: continue sflowd_argv = [] for idx, net_netif in list(localnetif.net._netif.items()): candidate_node = net_netif.node # skip our own interface if localnetif == net_netif: continue # found peering link # enable netflow on this interface if not node.netid == net_netif.node.netid and \ service_flags.EGP in net_netif.node.services: # get SNMP idx of this interface result, stdouterr = node.cmdresult( ['/opt/BENOCS/bin/ifindex', str(localnetif.name)]) if result != 0: node.warn(('Could not determine SNMP interface number ' 'for interface: %s - error: %s' % ( str(localnetif.name), str(stdouterr)))) sflowd_argv.append((' -i %s' % str(localnetif.name))) else: stdouterr = stdouterr.decode().strip() sflowd_argv.append((' -i %s:%s' % (str(stdouterr), str(localnetif.name)))) sflowd_argv.append((' -p /var/run/softflowd.%s.pid' % (str(localnetif.name)))) sflowd_argv.append((' -c /var/run/softflowd.%s.ctl' % (str(localnetif.name)))) # although, these options erase themself, somehow it won't start otherwise sflowd_argv.append(' -D') #/usr/local/sbin/softflowd -6 -i 255:eth2 -n 172.16.56.11:2055 -Pudp -v9 -ttcp=3 -ttcp.fin=3 -tmaxlife=5 -p /var/run/softflowd.eth2.pid -c /var/run/softflowd.eth2.ctl -D & # TODO: make this work when multiple collectors are present if len(collectors) > 0: config_list.extend(['bash startprobe.sh ', '"', ''.join(base_sflowd_argv), ''.join(sflowd_argv), '" ', collectors[0], ' ', str(node.getLoopbackIPv4()), ' &', '\n']) #config_list.extend(['bash startprobe.sh ', '"', ''.join(base_sflowd_argv), # ''.join(sflowd_argv), '" ', collectors[0], ' &', '\n']) # skip checking of other nodes on this link. they wouldn't # change any behavior, anyway. continue with next local # interface break return ''.join(config_list)