Planet Collab

🔒
❌ About FreshRSS
There are new articles available, click to refresh the page.
Yesterday — April 19th 2021Your RSS feeds
Before yesterdayYour RSS feeds

Name:Wreck, vulnérabilité Internet du jour

Comme souvent, une vulnérabilité logicielle a reçu un nom commercial (« Name:Wreck », notez le deux-points) et a eu droit à des articles dans les médias. Plongeons-nous un peu dans cette vulnérabilité et ce qu'elle nous apprend.

Name:Wreck est décrite dans un rapport (en anglais) de la société Forescout dont je vous recommande la lecture, c'est bien expliqué et avec une dose relativement limitée de sensationnalisme et de marketing. Name:Wreck n'est pas, comme cela a parfois été dit, une « vulnérabilité DNS » ou une « faille DNS » mais une bogue dans des logiciels client DNS. La bogue exploite une fonction peu connue du DNS, la compression des données dans les réponses. Comme le même nom de domaine peut apparaitre plusieurs fois dans une réponse DNS, l'encodage des noms dans le paquet peut se faire en ne mettant qu'une fois le nom et, le reste du temps, en mettant un pointeur vers ce nom. J'ai simplifié, pour avoir tous les détails, il faut lire le RFC 1035, section 4.1.4. (Notez que le rapport mentionne d'autres vulnérabilités, qui n'ont pas grand'chose à voir avec les pointeurs de compression.)

Si vous êtes programmeuse ou programmeur, vous avez déjà senti le problème : que se passe-t-il, par exemple, si le pointeur pointe en dehors du paquet ? Eh bien vous avez gagné, ce genre de problèmes est fréquent, beaucoup de mises en œuvre du DNS analysent les paquets sans faire assez attention. La section 6 du rapport cité plus haut liste un certain nombre d'erreurs courantes dans l'analyse des paquets DNS. Ces erreurs sont encore plus graves si on programme en C, langage qui, par défaut, vous laissera écrire au-delà des bornes. J'ajoute que mon expérience personnelle d'analyse de paquets DNS réels montre que les paquets mal formés sont une réalité, soit par désir de malveillance, soit par erreur. Ainsi, comme le note la sous-section 6.5 du rapport, un client DNS qui ferait une boucle sur le nombre d'enregistrements dans une section DNS sans précautions découvrirait rapidement que les paquets annonçant des milliers d'enregistrements, mais de taille bien trop courte pour les contenir, existent en vrai dans l'Internet. La règle de base de l'analyse de paquets entrants « soyez paranoïaques » s'applique au DNS.

Donc, en envoyant un paquet soigneusement calculé, avec des pointeurs de compression incorrects, on peut déclencher une boucle sans fin chez le client, ou un plantage, ou, pire, une exécution de code. Notons que si tout programme, quel que soit le langage dans lequel il est écrit, peut être vulnérable aux deux premières conséquences, la possibilité qu'une bogue mène à une exécution de code est quand même assez spécifique à C. Cela pourrait être un argument pour prôner l'utilisation de langages supposés plus sûrs, comme Rust (après, comme je n'ai pas appris à programmer en Rust, je réserve mon opinion).

La vulnérabilité existe par exemple dans le client DNS du système d'exploitation Nucleus de Siemens, conçu pour les objets connectés (cf. l'avis de sécurité). Elle touche aussi le système d'exploitation FreeBSD (cf. l'avis). Un des mérites des auteurs de l'étude est en effet de ne pas s'être limités aux clients DNS classiques mais d'avoir regardé d'autres logiciels qui analysent des informations DNS. C'est le cas des clients DHCP, qui peuvent recevoir des informations DNS, comme la liste des domaines à ajouter aux noms cherchés (option 119 en DHCP v4). En l'occurrence, chez FreeBSD, c'est en effet le client dhclient qui était vulnérable. (Quoique certaines mesures de protection peuvent, si elles sont utilisées, limiter les conséquences de la faille.)

Bien, donc, la faille existe. Maintenant, soyons positifs, agissons. Quelles sont les actions possibles ? Évidemment, les auteurs des logiciels concernés ont patché. Mais cela ne concerne que le code d'origine, pas toutes ses utilisations, loin en aval. Ce n'est pas parce qu'un patch existe chez FreeBSD, ou même qu'une nouvelle version de ce système d'exploitation sort, que toutes les machines FreeBSD de la planète vont recevoir le nouveau code. En outre, FreeBSD est souvent utilisé indirectement, par des gens qui ne savent même pas que le joli boitier très cher qu'ils ont acheté (répartiteur de charge, pare-feu, etc) utilise en fait FreeBSD. Ces boitiers spécialisés utilisent souvent des versions très en retard des logiciels (libres ou privateurs) qu'ils intègrent. Des versions vulnérables continueront donc à être en production pendant longtemps.

Et c'est encore pire dans le monde merveilleux de l'« Internet des Objets ». Là, la règle est le n'importe quoi, des objets vendus sans aucune mise à jour, ou bien une mise à jour compliquée, et qui ne dure de toute façon pas éternellement. Là, on peut parier que les versions vulnérables dureront bien plus longtemps. Un bonne lecture à rappeler est le RFC 8240, le compte-rendu d'un atelier IAB sur cette question de la mise à jour des objets connectés. Au passage, ce problème a une composante technique (ce sur quoi travaille le groupe de travail IETF SUIT) et surtout une composante business. Rien n'oblige les vendeurs d'objets connectés à assurer une maintenance rapide et correcte de leurs logiciels sur le long terme.

Bon, alors que faire en attendant ? Le rapport suggère d'isoler et de segmenter, pour éviter que les objets vulnérables se trouvent directement exposés au grand méchant Internet. C'est par exemple l'argument de Paul Vixie quand il dit qu'il faut s'assurer que les objets en entreprise ne parlent pas directement à des serveurs DNS externes mais passent forcément par un résolveur interne (qui ne leur enverra que des paquets DNS correctement formés). Le problème est que cela suppose que l'entreprise ait un résolveur interne, correct, à jour, qui rende le service attendu… (Par exemple, beaucoup de ces résolveurs internes ne valident pas.) Autrement, pas mal d'objets (via une décision de leur programmeur, ou de leur utilisateur) vont essayer de court-circuiter le résolveur local.

Et à l'IETF, peut-on faire quelque chose ? Changer le protocole DNS pour supprimer la compression n'est clairement pas possible, mais on pourrait attirer l'attention des programmeuses et des programmeurs sur ces dangers. C'est ce que propose un Internet-Draft écrit par les auteurs du rapport Name:Wreck, draft-dashevskyi-dnsrr-antipatterns. Le rapport suggère également de modifier le RFC 5625, qui dit qu'un relais DNS peut jeter les paquets mal formés. Le rapport suggère de dire qu'il le doit. Le problème est que certains de ces relais analysent la totalité des paquets (et peuvent donc les « proprifier ») alors que d'autres passent juste des bits et ne savent donc pas quels sont les paquets incorrects.

On peut quand même en tirer une leçon pour la conception de systèmes informatiques critiques : la compression dans le DNS est compliquée, mal spécifiée, et dangereuse. Comme la fragmentation/réassemblage dans IP, elle a déjà mené à pas mal de failles. On peut donc rappeler que la complexité est l'ennemie de la sécurité et que, pour gagner quelques octets, les auteurs du DNS ont créé une fonction dangereuse. Pensez-y la prochaine fois que vous entendrez quelqu'un dire que rajouter « juste une petite fonction simple » dans une spécification ou un code ne peut pas poser de problème.

Automate Cisco Router and Switches IOS Upgrade in Bulk using Python

April 13th 2021 at 20:24

Automate IOS upgrade for Cisco Routers and Cisco Switches in Bulk

I am new to python and have written this script based on my experience so far with python and I am sure that this script can be optimized and enhanced in much better way. Please do share your comments/review and optimization ideas.

Upgrading Cisco Routers and Switches is fun and easy but when the estate is huge and there are different models of those switches and routers, then it is really a painful task. As this is ongoing activity in any business as Cisco releases new IOS versions to fix vulnerabilities and bugs. In order to mitigate the vulnerabilities, any organization would prefer to upgrade their devices to the latest and greatest stable version. To ease the work, you can use “Automation” and get it completed without much human effort.

The script I have written is for Cisco 2801 and Cisco 2811 and I have tested it in my lab multiple times and it was working as expected. You can modify the script based on your business requirement. I am using netmiko in the script.  In case if you missed to read the previous article on Netmiko, please feel free to read it.

Netmiko SSH – Python Automation on Cisco Routers and Switches using SSH

Here is the YouTube video on automating ciscoIOS upgrade in bulk for cisco routers and cisco switches using Python script

 

When python script is ran, it will follow the below sequence:

  • The script will fetch a pre-upgrade report and the report will have information (like IP address, hostname, uptime, current version, current image, serial number, device model and device memory of the router) before it is upgraded.
  • Then it will push the IOS image on the cisco router/switch.
  • It will check the MD5 checksum.
  • It will change the boot configuration and save the configuration.
  • It will then reload the router.
  • The script will then wait for 300 seconds and then it will fetch a post-upgrade report.

The following files will be generated by the python script while running the script:

  • Pre-Upgrade.csv
  • Post-Upgrade.csv
  • Logs.txt

Below is the python script to automate Cisco IOS upgrade in bulk.

#############################################
####	Cisco IOS Upgrade in Bulk    	####
####	Script written by UC Collabing	####
####	https://www.uccollabing.com		####
#############################################

import subprocess, re, time, netmiko
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoTimeoutException
from netmiko.ssh_exception import SSHException
from netmiko.ssh_exception import AuthenticationException
from netmiko import SCPConn
from datetime import datetime

#Important parameters that can be changed and controlled from here#

ip_list = ['192.168.1.179', '192.168.1.178']

#Cisco IOS 2801 Data
new_ios_2801 = "c2801-ipvoice_ivs-mz.150-1.M7.bin"
new_ios_2801_size = "41735808"
new_ios_2801_md5 = "66c50292167f2b1c1ccd9ead3d5a5db4"


#Cisco IOS 2811 Data
new_ios_2811 = "c2800nm-ipvoice_ivs-mz.151-2.T1.bin"
new_ios_2811_size = "51707860"
new_ios_2811_md5 = "bf3e0811b5626534fd2e4b68cdd042df"

copy_from = "tftp"
copy_to = "flash:"
tftp_ip = "192.168.1.100"
reload_wait_time = "300"
auto_copy_to_flash = "Yes"
auto_change_boot_sequence ="Yes"
auto_reload = "Yes"

#########################################



#Creating the CSV files for pre and post upgrade#

#clearing the old data from the CSV file and writing the headers
f = open("pre_upgrade.csv", "w+")
f.write("IP Address, Hostname, Uptime, Current_Version, Current_Image, Serial_Number, Device_Model, Device_Memory")
f.write("\n")
f.close()


#clearing the old data from the CSV file and writing the headers
f = open("post_upgrade.csv", "w+")
f.write("IP Address, Hostname, Uptime, Current_Version, Current_Image, Serial_Number, Device_Model, Device_Memory")
f.write("\n")
f.close()


#clearing the old data from the logs file and writing the headers
f = open("logs.txt", "w+")
f.close()


now = datetime.now()
logs_time = now.strftime("%H:%M:%S")


#############################################################################################################################



def preupgrade():

	
	for ip in ip_list:
		cisco = {
		'device_type':'cisco_ios_telnet',
		'ip':ip,
		'username':'cisco',     #ssh username
		'password':'cisco',  #ssh password
		'secret': 'cisco',   #ssh_enable_password
		'ssh_strict':False,  
		'fast_cli':False,
		}
		
		now = datetime.now()
		logs_time = now.strftime("%H:%M:%S")
		print("" + logs_time + ": " + ip  + " Checking this device, Collecting pre-report ")
		#handling exceptions errors
		
		try:
			net_connect = ConnectHandler(**cisco)
		
		except (NetMikoTimeoutException, AuthenticationException, SSHException, ValueError, TimeoutError, ConnectionError, ConnectionResetError, OSError):
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " device login issue " + "\n" )
			f.close()
			continue

		try:
			net_connect.enable()

		
		#handling exceptions errors		
		except (NetMikoTimeoutException, AuthenticationException, SSHException, ValueError, TimeoutError, ConnectionError, ConnectionResetError):
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " device login issue " + "\n" )
			f.close()
			continue
		

		#list where informations will be stored
		pre_upgrade_devices = []

				
		# execute show version on router and save output to output object	
		sh_ver_output = net_connect.send_command('show version')   

		#finding hostname in output using regular expressions
		regex_hostname = re.compile(r'(\S+)\suptime')
		hostname = regex_hostname.findall(sh_ver_output)

		#finding uptime in output using regular expressions
		regex_uptime = re.compile(r'\S+\suptime\sis\s(.+)')
		uptime = regex_uptime.findall(sh_ver_output)
		uptime = str(uptime).replace(',' ,'').replace("'" ,"")
		uptime = str(uptime)[1:-1] 
		
		
		#finding version in output using regular expressions
		regex_version = re.compile(r'Cisco\sIOS\sSoftware.+Version\s([^,]+)')
		version = regex_version.findall(sh_ver_output)

		#finding serial in output using regular expressions
		regex_serial = re.compile(r'Processor\sboard\sID\s(\S+)')
		serial = regex_serial.findall(sh_ver_output)

		#finding ios image in output using regular expressions
		regex_ios = re.compile(r'System\simage\sfile\sis\s"([^ "]+)')
		ios = regex_ios.findall(sh_ver_output)

		#finding model in output using regular expressions
		regex_model = re.compile(r'[Cc]isco\s(\S+).*memory.')
		model = regex_model.findall(sh_ver_output)
		

		#finding the router's memory using regular expressions
		regex_memory = re.search(r'with (.*?) bytes of memory', sh_ver_output).group(1)
		memory = regex_memory
		
		
		
		#append results to table [hostname,uptime,version,serial,ios,model]
		pre_upgrade_devices.append([ip, hostname[0],uptime,version[0],ios[0], serial[0],model[0], memory])
		
		

		#print all results (for all routers) on screen    
		for i in pre_upgrade_devices:
			i = ", ".join(i)	  
			f = open("pre_upgrade.csv", "a")
			f.write(i)
			f.write("\n")
			f.close()	
			
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
	
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " collecting pre upgrade report " + "\n" )
			f.close()
		
			#If Auto Copy to flash is enabled - Then start copying the files to Flash#				
		if auto_copy_to_flash == "Yes":
			#print("Checking Auto Copy to Flash as Yes")
			
		
			#Check necessary space on Flash:#	
			output = net_connect.send_command('show flash')
			output = re.findall(r"\w+(?= bytes available)", output)
			output = ", ".join(output)

			if model[0] == "2801":		
				check_if_space_available = int(output) - int(new_ios_2801_size)
				#print(str(check_if_space_available))
				
				if int(check_if_space_available) > 0 :
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " Sufficient space available ")
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " Sufficent space available" + "\n" )
					f.close()
					time.sleep(2)
					pass
					
				elif int(check_if_space_available) < 0: now = datetime.now() logs_time = now.strftime("%H:%M:%S") print("" + logs_time + ": " + ip + " Not enough space ") f = open("logs.txt", "a") f.write("" + logs_time + ": " + ip + " not enough space" + "\n" ) f.close() continue if model[0] == "2811": check_if_space_available = int(output) - int(new_ios_2811_size) #print(str(check_if_space_available)) if int(check_if_space_available) > 0 :
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " Sufficient space available ")
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " Sufficent space available" + "\n" )
					f.close()
					time.sleep(2)
					pass
					
				elif int(check_if_space_available) < 0:	
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " Not enough space ")
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " not enough space" + "\n" )
					f.close()
					continue


					
			#Copy TFTP to FLASH#
			command = "copy " + copy_from + " " + copy_to
			start_time = datetime.now()
			output = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=1)
			
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			print("" + logs_time + ": " + ip  + " " + output)
			#print(output)
			
			#Entering the TFTP IP Address#
			command = tftp_ip
			start_time = datetime.now()
			#output = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=2)
			output = net_connect.send_command(command, expect_string=r']?')
			
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			print("" + logs_time + ": " + ip  + " " + output)
				
			
			#If the router model is 2801 - Run this code#
			if model[0] == "2801":			
				command = new_ios_2801
				start_time = datetime.now()
				#output = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=1)
				output = net_connect.send_command(command, expect_string=r']?')
				now = datetime.now()
				logs_time = now.strftime("%H:%M:%S")
				print("" + logs_time + ": " + ip  + " " + output)
				
				command = new_ios_2801
				start_time = datetime.now()
				#net_connect.send_config_set(config_commands)
				output = net_connect.send_command_timing(command, delay_factor=10, strip_prompt=False, strip_command=False)
				now = datetime.now()
				logs_time = now.strftime("%H:%M:%S")
				print("" + logs_time + ": " + ip  + " " + output)

									
				if re.search(r'\sbytes copied\b',output):
    					
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " File copied successfully ")	
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " file copied successfully" + "\n" )
					f.close()
					
					
					
					command = "verify /md5 flash:" + new_ios_2801
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					#output = net_connect.send_command(command, expect_string=r']?')
					output = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=5)
					print("" + logs_time + ": " + ip  + "Calculated MD5 is : " + output + "\n" "Expected MD5 is : " + new_ios_2801_md5 )
					try:
						output = re.search(' = (\w+)',output)
						print(output)	
						
					except AttributeError:
						output = re.search(' = (\w+)',output), output.group(1)
						#print(output.group(1))	
					
					if new_ios_2801_md5 == str(output.group(1)):
    					
						now = datetime.now()
						logs_time = now.strftime("%H:%M:%S")
						print("" + logs_time + ": " + ip  + " MD5 checksum verified ")
						
						f = open("logs.txt", "a")
						f.write("" + logs_time + ": " + ip  + " MD5 checksum verified" + "\n" )
						f.close()
						
						
						
											
					elif new_ios_2801_md5 != str(output.group(1)):
						now = datetime.now()
						logs_time = now.strftime("%H:%M:%S")
						print("" + logs_time + ": " + ip  + " MD5 checksum mismatch ")
				
						f = open("logs.txt", "a")
						f.write("" + logs_time + ": " + ip  + " MD5 checksum mismatch" + "\n" )
						f.close()					
						
						continue
				
								
				
				elif re.search(r'\%Error copying\b',output):
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " Error copying the file ")
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " error copying file" + "\n" )
					f.close()
					continue
					
				elif re.search(r'\%Error opening\b',output):
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " File does not exist ")
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " file does not exist" + "\n" )
					f.close()

					continue
					
				elif re.search(r'\bAccessing',output):
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " Please check your TFTP/SCP service/network network connectivity ")
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " check your TFTP/SCP service/network network connectivity" + "\n" )
					f.close()				


					continue
					
					
		

			
			#If the router model is 2811 - Run this code#
			elif model[0] == "2811":			
				command = new_ios_2811
				start_time = datetime.now()
				#output = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=1)
				output = net_connect.send_command(command, expect_string=r']?')
				now = datetime.now()
				logs_time = now.strftime("%H:%M:%S")
				print("" + logs_time + ": " + ip  + " " + output)
				
				command = new_ios_2811
				start_time = datetime.now()
				#net_connect.send_config_set(config_commands)
				output = net_connect.send_command_timing(command, delay_factor=10, strip_prompt=False, strip_command=False)
				now = datetime.now()
				logs_time = now.strftime("%H:%M:%S")
				print("" + logs_time + ": " + ip  + " " + output)
									
				if re.search(r'\sbytes copied\b',output):
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " File copied successfully ")
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " file copied successfully" + "\n" )
					f.close()

					
					
					command = "verify /md5 flash:" + new_ios_2811
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					#output = net_connect.send_command(command, expect_string=r']?')
					output = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=5)
					print("" + logs_time + ": " + ip  + "Calculated MD5 is : " + output + "\n" "Expected MD5 is : " + new_ios_2811_md5 )
					#print(output)
					try:
						output = re.search(' = (\w+)',output)
						#print(output)	
						
					except AttributeError:
						output = re.search(' = (\w+)',output), output.group(1)
						#print(output.group(1))	
					
					if new_ios_2811_md5 == str(output.group(1)):
						now = datetime.now()
						logs_time = now.strftime("%H:%M:%S")
						print("" + logs_time + ": " + ip  + " MD5 checksum successfully matched ")
						
						f = open("logs.txt", "a")
						f.write("" + logs_time + ": " + ip  + " MD5 checksum verified" + "\n" )
						f.close()

						
											
					elif new_ios_2811_md5 != str(output.group(1)):
						now = datetime.now()
						logs_time = now.strftime("%H:%M:%S")
						print("" + logs_time + ": " + ip  + " MD5 checksum mismatch ")
					
						f = open("logs.txt", "a")
						f.write("" + logs_time + ": " + ip  + " MD5 checksum mismatch" + "\n" )
						f.close()					

						continue
					
								
				
				elif re.search(r'\%Error copying\b',output):
    					
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " Error copying the file ")	
					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " error copying file" + "\n" )
					f.close()
					continue
					
				elif re.search(r'\%Error opening\b',output):
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " File does not exist ")	

					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " file does not exist" + "\n" )
					f.close()	
					continue	
					
				elif re.search(r'\bAccessing',output):
					now = datetime.now()
					logs_time = now.strftime("%H:%M:%S")
					print("" + logs_time + ": " + ip  + " Please check your TFTP/SCP service/network network connectivity ")

					f = open("logs.txt", "a")
					f.write("" + logs_time + ": " + ip  + " check your TFTP/SCP service/network network connectivity" + "\n" )
					f.close()				
					continue		
					
					
							

					
			#If Auto Copy to flash is disabled - Then continue to next step#		
		elif auto_copy_to_flash == "No":
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			print("" + logs_time + ": " + ip  + " Auto copy to flash is set as No ")
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " Auto copy to flash is set as No " + "\n" )
			f.close()
			pass				
						
		if auto_change_boot_sequence == "Yes":		
		
			#Enter the New IOS#
			output = net_connect.send_command('show version') 
			regex_ios = re.compile(r'System\simage\sfile\sis\s"([^ "]+)')
			current_ios = regex_ios.findall(output)
			current_ios = ", ".join(current_ios)
			
			remove_boot = "no boot system"
			remove_boot = net_connect.send_config_set(remove_boot)
			

			if model[0] == "2801":
				add_boot1 = "boot system flash:" + new_ios_2801
				add_boot1 = net_connect.send_config_set(add_boot1)
				
			elif model[0] == "2811":
				add_boot1 = "boot system flash:" + new_ios_2811
				add_boot1 = net_connect.send_config_set(add_boot1)
				
			

			add_boot2 =  "boot system " + str(current_ios)
			add_boot2 = net_connect.send_config_set(add_boot2)
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			print("" + logs_time + ": " + ip  + " Boot sequence changed ")
			


			#write_config = net_connect.send_command('wr mem', expect_string='[OK]')
			command = "wr mem"
			write_config = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=2)
			

			command = ""
			write_config = net_connect.send_command_timing(command, strip_prompt=False, strip_command=False, delay_factor=2)
			

			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			print("" + logs_time + ": " + ip  + " Configuration saved ")
			
			
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " configuration saved" + "\n" )
			f.close()


						
		elif auto_change_boot_sequence == "No":
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			print("" + logs_time + ": " + ip  + " Please change the boot sequence manually! and proceed with reload ")
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " Please change the boot sequence manually! and proceed with reload" + "\n" )
			f.close()
			pass

				
		if auto_reload == "Yes":
		
			try:
				
				confirm_reload = net_connect.send_command('reload', expect_string='[confirm]')
				confirm_reload = net_connect.send_command('\n', expect_string='[confirm]')
				now = datetime.now()
				logs_time = now.strftime("%H:%M:%S")
				
				f = open("logs.txt", "a")
				f.write("" + logs_time + ": " + ip  + " Reload command sent" + "\n" )
				f.close()
				
				print("" + logs_time + ": " + ip  + " Sending reload command ")

			except Exception as e:
				print(e)
				f = open("logs.txt", "a")
				f.write("" + logs_time + ": " + ip  + " Reload command sent" + "\n" )
				f.close()
				
				print("" + logs_time + ": " + ip  + " Sending reload command ")



		elif auto_reload== "No":
    		
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			print("" + logs_time + ": " + ip  + " Please reload the router manually ")

			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " Please reload the router manually" + "\n" )
			f.close()

			pass
					
					
						
preupgrade()

def sleeptime():
	now = datetime.now()
	logs_time = now.strftime("%H:%M:%S")
	print("" + logs_time + ": Wait time activated, please wait for " + str(reload_wait_time) + " seconds")
	time.sleep(int(reload_wait_time))

sleeptime()	
					
def	postupgrade():

	
	for ip in ip_list:
		cisco = {
		'device_type':'cisco_ios_telnet',
		'ip':ip,
		'username':'cisco',     #ssh username
		'password':'cisco',  #ssh password
		'secret': 'cisco',   #ssh_enable_password
		'ssh_strict':False,  
		'fast_cli':False,
		}
	
		now = datetime.now()
		logs_time = now.strftime("%H:%M:%S")
		print("" + logs_time + ": " + ip  + " Checking this device, Collecting post-report ")
					
		try:
			#time.sleep(int(reload_wait_time))
			net_connect = ConnectHandler(**cisco)
		except (NetMikoTimeoutException, AuthenticationException, SSHException, ValueError, TimeoutError, ConnectionError, ConnectionResetError):
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " device login issue " + "\n" )
			f.close()
			continue

		try:
			net_connect.enable()

			

		#handling exceptions errors		
		except (NetMikoTimeoutException, AuthenticationException, SSHException, ValueError, TimeoutError, ConnectionError, ConnectionResetError, OSError):
			now = datetime.now()
			logs_time = now.strftime("%H:%M:%S")
			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " device login issue " + "\n" )
			f.close()
			continue
		
		#list where informations will be stored
		post_upgrade_devices = []
		
		# execute show version on router and save output to output object	
		sh_ver_output = net_connect.send_command('show version')   

		#finding hostname in output using regular expressions
		regex_hostname = re.compile(r'(\S+)\suptime')
		hostname = regex_hostname.findall(sh_ver_output)

		#finding uptime in output using regular expressions
		regex_uptime = re.compile(r'\S+\suptime\sis\s(.+)')
		uptime = regex_uptime.findall(sh_ver_output)
		uptime = str(uptime).replace(',' ,'').replace("'" ,"")
		uptime = str(uptime)[1:-1] 
		
		
		#finding version in output using regular expressions
		regex_version = re.compile(r'Cisco\sIOS\sSoftware.+Version\s([^,]+)')
		version = regex_version.findall(sh_ver_output)

		#finding serial in output using regular expressions
		regex_serial = re.compile(r'Processor\sboard\sID\s(\S+)')
		serial = regex_serial.findall(sh_ver_output)

		#finding ios image in output using regular expressions
		regex_ios = re.compile(r'System\simage\sfile\sis\s"([^ "]+)')
		ios = regex_ios.findall(sh_ver_output)

		#finding model in output using regular expressions
		regex_model = re.compile(r'[Cc]isco\s(\S+).*memory.')
		model = regex_model.findall(sh_ver_output)
		

		#finding the router's memory using regular expressions
		regex_memory = re.search(r'with (.*?) bytes of memory', sh_ver_output).group(1)
		memory = regex_memory
		
		
		
		#append results to table [hostname,uptime,version,serial,ios,model]
		post_upgrade_devices.append([ip, hostname[0],uptime,version[0],ios[0], serial[0],model[0], memory])
				


	#print all results (for all routers) on screen    
		for i in post_upgrade_devices:
			i = ", ".join(i)	  
			f = open("post_upgrade.csv", "a")
			f.write(i)
			f.write("\n")
			f.close()

			f = open("logs.txt", "a")
			f.write("" + logs_time + ": " + ip  + " collecting post upgrade report " + "\n" )
			f.close()

postupgrade()

 

Note: We recommend you to try it in your lab first before you try it in production. Please try this at your own risk, we are not responsible for any failure/damages to your devices.

The post Automate Cisco Router and Switches IOS Upgrade in Bulk using Python appeared first on UC Collabing.

UC Today ‘Upselling Alert’

April 8th 2021 at 11:29

The post UC Today ‘Upselling Alert’ appeared first on telisca.

Cavanna, paléontologue !

Si, comme beaucoup de personnes (comme moi, par exemple), vous ignoriez que Cavanna était féru de paléontologie, vous allez l'apprendre dans ce court livre où l'auteur nous raconte ses échanges scientifiques avec le fondateur de Charlie Hebdo.

Cavanna avait de nombreuses cordes à son arc. Mais ce récit de Pascal Tassy se focalise sur une seule corde : la passion du « rital » pour l'étude des espèces disparues. Cavanna était curieux de sciences et aimait discuter avec les scientifiques. Son arrivée à la soutenance de thèse de l'auteur (thèse sur les mastodontes) avait sérieusement déstabilisé le bientôt docteur. Ils ont finalement parlé d'adaptation, de sélection naturelle, de cladistique, d'écologie… pendant de nombreuses années.

Si Cavanna et Pascal Tassy étaient d'accord sur beaucoup de choses (par exemple pour se moquer des créationnistes), il leur restait des sujets de controverses. J'ai ainsi appris que Cavanna, contrairement à son ami, était plutôt favorable au transhumanisme et tenté par l'idée d'immatérialisme.

Il était même prévu entre les deux amis d'écrire ensemble un livre… qui ne s'est finalement pas fait. À défaut, vous aurez dans ce récit quelques idées sur ce qu'aurait pu être ce livre.

Autre compte-rendu de ce livre, dans Charlie Hebdo.

RFC 9018: Interoperable Domain Name System (DNS) Server Cookies

Le RFC 7873 normalisait un mécanisme, les cookies, pour qu'un serveur DNS authentifie raisonnablement l'adresse IP du client (ce qui, normalement, n'est pas le cas en UDP). Comme seul le serveur avait besoin de reconnaitre ses cookies, le RFC 7873 n'imposait pas un algorithme particulier pour les générer. Cela posait problème dans certains cas et notre nouveau RFC propose donc un mécanisme standard pour fabriquer ces cookies.

L'un des scénarios d'utilisation de ces « cookies standards » est le cas d'un serveur anycast dont on voudrait que toutes les instances génèrent des cookies standardisés, pour qu'une instance puisse reconnaitre les cookies d'une autre. Le RFC 7873, section 6, disait bien que toutes les instances avaient intérêt à partir du même secret mais ce n'était pas plus détaillé que cela. La situation actuelle, où chaque serveur peut faire différemment, est décrite dans le RFC par un mot en anglais que je ne connaissais pas, gallimaufry. D'où l'idée de spécifier cet algorithme, pour simplifier la vie des programmeuses et programmeurs avec un algorithme de génération de cookie bien étudié et documenté ; plus besoin d'en inventer un. Et cela permet de créer un service anycast avec des logiciels d'auteurs différents. S'ils utilisent cet algorithme, ils seront compatibles. Il ne s'agit que d'une possibilité : les serveurs peuvent utiliser cet algorithme mais ne sont pas obligés, le RFC 7873 reste d'actualité.

Comment, donc, construire un cookie ? Commençons par celui du client (section 3). Rappel : le but est d'authentifier un minimum donc, par exemple, le client doit choisir un cookie différent par serveur (sinon, un serveur pourrait se faire passer pour un autre, d'autant plus que le cookie circule en clair), et, donc, il faut utiliser quelque chose de spécifique au serveur dans l'algorithme, par exemple son adresse IP. Par contre, pas besoin de le changer souvent, il peut parfaitement durer des mois, sauf évidemment si un élément entrant dans sa construction change, ou est compromis. Autrefois, il était suggéré d'utiliser l'adresse IP du client dans la construction du cookie client, mais cette suggestion a été retirée car le logiciel ne connait parfois son adresse IP que trop tard (ça dépend de l'API réseau utilisée et, par exemple, avec l'API sockets de si on a déjà fait un bind() et, de toute façon, si on est derrière un routeur NAT, connaitre l'adresse IP locale ne sert pas à grand'chose). Néanmoins, pour éviter qu'un cookie ne permette à un observateur de relier deux requêtes d'une même machine, le cookie doit changer quand l'adresse IP change, comme rappelé par la section 8.1. (C'est particulièrement important si on utilise des techniques de protection de la vie privée comme celle du RFC 8981.)

Voilà, c'est tout parce que ce qui est important dans notre RFC, c'est le cookie serveur (section 4), puisque c'est là qu'on voudrait un cookie identique pour toutes les instances du service. Les éléments utilisés pour le générer sont le cookie du client, l'adresse IP du serveur, quelques métadonnées et un secret (qu'il faudra donc partager au sein du service anycast). Le secret changera, par exemple une fois par mois. Une fois qu'on a tous ces éléments, on va ensuite condenser le tout, ici avec SipHash (cf. J. Aumasson, et D. J. Bernstein, « SipHash: A Fast Short- Input PRF »). (Parmi les critères de choix d'une fonction de condensation, il y a les performances, un serveur DNS actif pouvant avoir à faire ce calcul souvent, pour vérifier les cookies.) Le cookie comprendra un numéro de version, un champ réservé, une estampille temporelle et le condensat. L'algorithme de génération du condensat inclus dans le cookie est donc : Condensat = SipHash-2-4 ( Cookie client | Version | Réservé | Estampille | Client-IP, Secret ), avec :

  • Le signe | indique la concaténation.
  • Le champ Version vaut actuellement 1 (les futures versions seront dans un registre IANA).
  • Le champ Réservé ne comporte pour l'instant que des zéros.
  • L'estampille temporelle sert à éviter les attaques par rejeu et permet de donner une durée de validité aux cookies (le RFC recommande une heure, avec cinq minutes de battement pour tenir compte des horloges mal synchronisées).

On a vu qu'il fallait changer le secret connu du serveur de temps en temps (voire plus rapidement s'il est compromis). Pour que ça ne casse pas tout (un serveur ne reconnaissant pas les cookies qu'il avait lui-même émis avec l'ancien secret…), il faut une période de recouvrement où le serveur connait déjà le nouveau secret (et accepte les cookies ainsi générés, par exemple par les autres instances du service anycast), puis une période où le serveur génère les cookies avec le nouveau secret, mais continue à accepter les cookies anciens (par exemple gardés par des clients). La section 5 rappelle, comme on le fait pour les remplacements de clés DNSSEC, de tenir compte des TTL pour calculer les délais nécessaires.

Si vous voulez mettre en œuvre vous-même cet algorithme, notez que l'annexe A du RFC contient des vecteurs de test, permettant de vérifier si vous ne vous êtes pas trompé.

La section 2 de notre RFC décrit les changements depuis le RFC 7873. Les algorithmes données comme simples suggestions dans les annexes A.1 et B.1 sont trop faibles et ne doivent pas être utilisés. Celui de l'annexe B.2 ne pose pas de problèmes de sécurité mais celui de notre nouveau RFC est préféré.

Plusieurs mises en œuvre de ce nouvel algorithme ont été faites, et leur interopérabilité testée (notamment au cours du hackathon de la réunion IETF 104 à Prague). Au moins BIND, Knot et getdns ont déjà cet algorithme dans leurs versions publiées.

Time Tracking Report: Mar 2021

April 2nd 2021 at 18:11

The first two weeks I started tracking time as usual with Boosted: Then I was faced with the decision with either continuing using it, buying the full features, or searching something similar that is free and fulfills my requirements. That is how I found aTimeLogger. I customized it and used for the rest of my ... Read more

The post Time Tracking Report: Mar 2021 appeared first on Keyboardbanger.com.

Time Tracking Report: Feb 2021

March 1st 2021 at 17:05

Time tracker project duration report feb 2021

The post Time Tracking Report: Feb 2021 appeared first on Keyboardbanger.com.

Time Tracking Report: Jan 2021

January 25th 2021 at 16:51

first, let us look at the week from 18 to 24 January: Then I decided not to track per week, but for the whole month:

The post Time Tracking Report: Jan 2021 appeared first on Keyboardbanger.com.

Ubuntu (Debian/Pop!OS) – How to configure static IP using Netplan

April 1st 2021 at 03:00

1. Check the files under /etc/netplan

bchoi@u20sn1:~$ ls /etc/netplan/
00-installer-config.yaml

bchoi@u20sn1:~$ cat /etc/netplan/00-installer-config.yaml

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp0s3:
      dhcp4: true
  version: 2

Optionally, if you plan to go back to the DHCP configuration, make a backup of the original file and keep it as a backup.

bchoi@u20sn1:~$ cp /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.backup

2. Reconfigure the file as below:

bchoi@u20sn1:~$ cat /etc/netplan/00-installer-config.yaml

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp0s3:
      dhcp4: false
      addresses:
        - 192.168.30.91/24
      gateway4: 192.168.130.1
      nameservers:
        addresses: [8.8.8.8,8.8.4.4]
    enp0s8:
      dhcp4: false
      addresses:
        - 192.168.56.91/24
  version: 2

We are configuring the primary and management interfaces above.

3. Apply the changes

bchoi@u20sn1:~$ sudo netplan apply
[sudo] password for bchoi: *********
bchoi@u20sn1:~$

4. Check interface configurations

  • Note: ifconfig is under “/sbin/ifconfig” directory

bchoi@u20sn1:~$ ifconfig enp0s3
enp0s3: flags=4163 mtu 1500
inet 192.168.130.91 netmask 255.255.255.0 broadcast 192.168.130.255
inet6 fe80::a00:27ff:fedc:68a5 prefixlen 64 scopeid 0x20
ether 08:00:27:dc:68:a5 txqueuelen 1000 (Ethernet)
RX packets 65774 bytes 98488217 (98.4 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6729 bytes 436729 (436.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

bchoi@u20sn1:~$ ifconfig enp0s8

enp0s8: flags=4163 mtu 1500
inet 192.168.156.91 netmask 255.255.255.0 broadcast 192.168.156.255
inet6 fe80::a00:27ff:fec7:c462 prefixlen 64 scopeid 0x20
ether 08:00:27:c7:c4:62 txqueuelen 1000 (Ethernet)
RX packets 2791 bytes 334791 (334.7 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1783 bytes 260035 (260.0 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

5. Check the default gateway and configuration

Method 1:

bchoi@u20sn1:~$ ip route show
default via 192.168.130.1 dev enp0s3 proto static
192.168.130.0/24 dev enp0s3 proto kernel scope link src 192.168.130.91
192.168.156.0/24 dev enp0s8 proto kernel scope link src 192.168.156.91

Method 2:

bchoi@u20sn1:~$ netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.130.1 0.0.0.0 UG 0 0 0 enp0s3
192.168.130.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s3
192.168.156.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s8

[Optional extras] 6. To check the ports opened for extra checking, use the following commands

bchoi@u20sn1:~$ netstat -tuna

bchoi@u20sn1:~$ traceroute http://www.google.com
traceroute to http://www.google.com (172.217.167.68), 30 hops max, 60 byte packets
1 _gateway (192.168.130.1) 0.282 ms 0.249 ms 0.224 ms
2 * * *


30 * * *

bchoi@u20sn1:~$ whois google.com
Domain Name: GOOGLE.COM
Registry Domain ID: 2138514_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.markmonitor.com
Registrar URL: http://www.markmonitor.com
Updated Date: 2019-09-09T15:39:04Z
Creation Date: 1997-09-15T04:00:00Z
Registry Expiry Date: 2028-09-14T04:00:00Z

italchemy

Fedora(/CentOS/Red Hat) – How to configure network using NetworkManager (nmcli) commands

April 1st 2021 at 02:35

1. Check status of NetworkManager

[bchoi@f33sn1 ~]$ nmcli general status
STATE CONNECTIVITY WIFI-HW WIFI WWAN-HW WWAN
connected full enabled enabled enabled enabled

2. Check the connection status

[bchoi@f33sn1 ~]$ nmcli -t -f STATE general
connected

3. Check UUID and Device name (I have two connected interfaces here, one for primary, one for management)

[bchoi@f33sn1 ~]$ nmcli con show -a
NAME UUID TYPE DEVICE
enp0s3 5ba2e0cc-3bd3-3814-9ff2-bead05343b83 ethernet enp0s3
enp0s8 22b55cab-9272-3a35-9047-9607681f84c0 ethernet enp0s8

4.Check device status

[bchoi@f33sn1 ~]$ nmcli dev status
DEVICE TYPE STATE CONNECTION
enp0s3 ethernet connected enp0s3
enp0s8 ethernet connected enp0s8
lo loopback unmanaged —

5. To view specific interface configuration

[bchoi@f33sn1 ~]$ ifconfig enp0s3
enp0s3: flags=4163 mtu 1500
inet 192.168.30.201 netmask 255.255.255.0 broadcast 192.168.30.255
inet6 fe80::a00:27ff:fe4e:4618 prefixlen 64 scopeid 0x20
ether 08:00:27:4e:46:18 txqueuelen 1000 (Ethernet)
RX packets 6667 bytes 7665579 (7.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2672 bytes 227364 (222.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

[bchoi@f33sn1 ~]$ ifconfig enp0s8
enp0s8: flags=4163 mtu 1500
inet 192.168.156.201 netmask 255.255.255.0 broadcast 192.168.56.255
inet6 fe80::a00:27ff:fec9:b7b prefixlen 64 scopeid 0x20
ether 08:00:27:c9:0b:7b txqueuelen 1000 (Ethernet)
RX packets 2544 bytes 310492 (303.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1224 bytes 189047 (184.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

6. Use ip addr show and grep command to get specific information

[bchoi@f33sn1 ~]$ ip addr | grep enp0s3
2: enp0s3: mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 192.168.30.201/24 brd 192.168.30.255 scope global noprefixroute enp0s3
[bchoi@f33sn1 ~]$ ip addr | grep enp0s8
3: enp0s8: mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 192.168.156.201/24 brd 192.168.156.255 scope global noprefixroute enp0s8

7. To change IP to static address

To configure the primary

[bchoi@f33sn1 ~]$ sudo nmcli connection modify enp0s3 IPv4.address 192.168.30.10/24
[bchoi@f33sn1 ~]$ sudo nmcli connection modify enp0s3 IPv4.gateway 192.168.30.1/24
[bchoi@f33sn1 ~]$ sudo nmcli connection modify enp0s3 IPv4.method manual

[Optional] To configure the management IP, you do not need to configure the gateway.

[bchoi@f33sn1 ~]$ sudo nmcli connection modify enp0s8 IPv4.address 192.168.56.50/24

[bchoi@f33sn1 ~]$ sudo nmcli connection modify enp0s8 IPv4.method manual

8. To change the DNS

[bchoi@f33sn1 ~]$ sudo nmcli connection modify enp0s3 IPv4.dns 8.8.8.8

9. Restart the interface, bring down and bring up

[bchoi@f33sn1 ~]$ sudo nmcli connection down enp0s3; sudo nmcli connection up enp0s3

10. Check gateway and IP

[bchoi@f33sn1 ~]$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.30.1 0.0.0.0 UG 100 0 0 enp0s3
192.168.30.0 0.0.0.0 255.255.255.0 U 100 0 0 enp0s3
192.168.156.0 0.0.0.0 255.255.255.0 U 101 0 0 enp0s8

italchemy

Ubuntu (Debian/Pop!OS) – How to configure static IP using Netplan

April 1st 2021 at 03:00

1. Check the files under /etc/netplan

bchoi@u20sn1:~$ ls /etc/netplan/
00-installer-config.yaml

bchoi@u20sn1:~$ cat /etc/netplan/00-installer-config.yaml

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp0s3:
      dhcp4: true
  version: 2

Optionally, if you plan to go back to the DHCP configuration, make a backup of the original file and keep it as a backup.

bchoi@u20sn1:~$ cp /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.backup

2. Reconfigure the file as below:

bchoi@u20sn1:~$ cat /etc/netplan/00-installer-config.yaml

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp0s3:
      dhcp4: false
      addresses:
        - 192.168.30.91/24
      gateway4: 192.168.130.1
      nameservers:
        addresses: [8.8.8.8,8.8.4.4]
    enp0s8:
      dhcp4: false
      addresses:
        - 192.168.56.91/24
  version: 2

We are configuring the primary and management interfaces above.

3. Apply the changes

bchoi@u20sn1:~$ sudo netplan apply
[sudo] password for bchoi: *********
bchoi@u20sn1:~$

4. Check interface configurations

  • Note: ifconfig is under “/sbin/ifconfig” directory

bchoi@u20sn1:~$ ifconfig enp0s3
enp0s3: flags=4163 mtu 1500
inet 192.168.130.91 netmask 255.255.255.0 broadcast 192.168.130.255
inet6 fe80::a00:27ff:fedc:68a5 prefixlen 64 scopeid 0x20
ether 08:00:27:dc:68:a5 txqueuelen 1000 (Ethernet)
RX packets 65774 bytes 98488217 (98.4 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6729 bytes 436729 (436.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

bchoi@u20sn1:~$ ifconfig enp0s8

enp0s8: flags=4163 mtu 1500
inet 192.168.156.91 netmask 255.255.255.0 broadcast 192.168.156.255
inet6 fe80::a00:27ff:fec7:c462 prefixlen 64 scopeid 0x20
ether 08:00:27:c7:c4:62 txqueuelen 1000 (Ethernet)
RX packets 2791 bytes 334791 (334.7 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1783 bytes 260035 (260.0 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

5. Check the default gateway and configuration

Method 1:

bchoi@u20sn1:~$ ip route show
default via 192.168.130.1 dev enp0s3 proto static
192.168.130.0/24 dev enp0s3 proto kernel scope link src 192.168.130.91
192.168.156.0/24 dev enp0s8 proto kernel scope link src 192.168.156.91

Method 2:

bchoi@u20sn1:~$ netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.130.1 0.0.0.0 UG 0 0 0 enp0s3
192.168.130.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s3
192.168.156.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s8

[Optional extras] 6. To check the ports opened for extra checking, use the following commands

bchoi@u20sn1:~$ netstat -tuna

bchoi@u20sn1:~$ traceroute http://www.google.com
traceroute to http://www.google.com (172.217.167.68), 30 hops max, 60 byte packets
1 _gateway (192.168.130.1) 0.282 ms 0.249 ms 0.224 ms
2 * * *


30 * * *

bchoi@u20sn1:~$ whois google.com
Domain Name: GOOGLE.COM
Registry Domain ID: 2138514_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.markmonitor.com
Registrar URL: http://www.markmonitor.com
Updated Date: 2019-09-09T15:39:04Z
Creation Date: 1997-09-15T04:00:00Z
Registry Expiry Date: 2028-09-14T04:00:00Z

❌