Technical World: 2025

Wednesday, July 30, 2025

Top Tech Picks of Aug 2025

best budget phone: POCO X7 Pro 5G https://amzn.to/3U4uItm best vfm tws: CMF BY NOTHING Buds 2a https://amzn.to/3IWnkOh best vfm powerbank: boAt Energyshroom PB400 Pro 20000mAh https://amzn.to/40KgBgt best vfm charger: Nu Republic Cybotron 45W Dual Port Gan Superfast Wall Charger https://amzn.to/4mjL9y3

Thursday, April 24, 2025

Fortigate config parser

this python script will take fortigate config file as input with name "fortigate_config.conf" and generate the excel file ipsec_tunnels.xlsx with all the ipsec tunnel details. save and run the python sccript below: import re import pandas as pd from pathlib import Path from openpyxl import Workbook from openpyxl.utils import get_column_letter def parse_phase1_config(config_text): """Parse config vpn ipsec phase1-interface section.""" tunnels = {} current_tunnel = None phase1_patterns = { "Interface": r"set interface \"(\S+)\"", "Type": r"set type (\S+)", "Remote Gateway": r"set remote-gw (\S+)", "Local Gateway": r"set local-gw (\S+)", "Proposal": r"set proposal (\S+)", "NAT Traversal": r"set nattraversal (\S+)", "DPD": r"set dpd (\S+)", "DPD Retry Count": r"set dpd-retrycount (\d+)", "DPD Retry Interval": r"set dpd-retryinterval (\d+)", "Mode": r"set mode (\S+)", # For dial-up (main/aggressive) "Mode CFG": r"set mode-cfg (\S+)", # For dial-up IP assignment "Auth User Group": r"set authusrgrp \"(\S+)\"", # For dial-up "Client IP Range": r"set ipv4-name \"(\S+)\"", # For dial-up # Note: PSK Secret omitted for security; add if needed } phase1_section = re.search(r"config vpn ipsec phase1-interface.*?end", config_text, re.DOTALL) if not phase1_section: return tunnels for line in phase1_section.group(0).splitlines(): line = line.strip() if line.startswith("edit "): current_tunnel = line.split('"')[1] tunnels[current_tunnel] = {} elif line.startswith("set ") and current_tunnel: for key, pattern in phase1_patterns.items(): match = re.match(pattern, line) if match: tunnels[current_tunnel][key] = match.group(1) elif line == "next": current_tunnel = None # Set defaults for missing fields for tunnel in tunnels.values(): for key in phase1_patterns: tunnel.setdefault(key, "N/A") return tunnels def parse_phase2_config(config_text): """Parse config vpn ipsec phase2-interface section.""" tunnels = {} current_tunnel = None phase2_patterns = { "Phase 1 Name": r"set phase1name \"(\S+)\"", "Source Subnet": r"set src-subnet (\S+ \S+)", "Destination Subnet": r"set dst-subnet (\S+ \S+)", "Source Port": r"set src-port (\d+)", "Destination Port": r"set dst-port (\d+)", "Protocol": r"set protocol (\d+)", "Proposal": r"set proposal (\S+)" } phase2_section = re.search(r"config vpn ipsec phase2-interface.*?end", config_text, re.DOTALL) if not phase2_section: return tunnels for line in phase2_section.group(0).splitlines(): line = line.strip() if line.startswith("edit "): current_tunnel = line.split('"')[1] tunnels[current_tunnel] = {} elif line.startswith("set ") and current_tunnel: for key, pattern in phase2_patterns.items(): match = re.match(pattern, line) if match: tunnels[current_tunnel][key] = match.group(1) elif line == "next": current_tunnel = None # Set defaults for missing fields for tunnel in tunnels.values(): for key in phase2_patterns: tunnel.setdefault(key, "N/A") return tunnels def parse_firewall_policies(config_text, tunnel_names): """Parse config firewall policy section for policies referencing tunnels.""" policies = {name: [] for name in tunnel_names} current_policy = None policy_patterns = { "Policy ID": r"edit (\d+)", "Source Interface": r"set srcintf \"(\S+)\"", "Destination Interface": r"set dstintf \"(\S+)\"", "Source Address": r"set srcaddr \"(\S+)\"", "Destination Address": r"set dstaddr \"(\S+)\"", "Service": r"set service \"(\S+)\"", "Action": r"set action (\S+)", "Schedule": r"set schedule \"(\S+)\"" } policy_section = re.search(r"config firewall policy.*?end", config_text, re.DOTALL) if not policy_section: return policies for line in policy_section.group(0).splitlines(): line = line.strip() if line.startswith("edit "): current_policy = {"Policy ID": line.split()[1]} elif line.startswith("set ") and current_policy is not None: for key, pattern in policy_patterns.items(): match = re.match(pattern, line) if match: current_policy[key] = match.group(1) elif line == "next" and current_policy: for tunnel_name in tunnel_names: if (current_policy.get("Source Interface") == tunnel_name or current_policy.get("Destination Interface") == tunnel_name): policies[tunnel_name].append(current_policy) current_policy = None return policies def parse_address_objects(config_text): """Parse config firewall address section for address objects (e.g., client IP pools).""" addresses = {} current_address = None address_patterns = { "Type": r"set type (\S+)", "Start IP": r"set start-ip (\S+)", "End IP": r"set end-ip (\S+)", "Subnet": r"set subnet (\S+ \S+)" } address_section = re.search(r"config firewall address.*?end", config_text, re.DOTALL) if not address_section: return addresses for line in address_section.group(0).splitlines(): line = line.strip() if line.startswith("edit "): current_address = line.split('"')[1] addresses[current_address] = {} elif line.startswith("set ") and current_address: for key, pattern in address_patterns.items(): match = re.match(pattern, line) if match: addresses[current_address][key] = match.group(1) elif line == "next": current_address = None return addresses def create_excel_from_configs(phase1_configs, phase2_configs, firewall_policies, address_objects, output_file="ipsec_tunnels.xlsx"): """Create an Excel file from parsed IPsec configurations with an index sheet using openpyxl.""" # Initialize workbook workbook = Workbook() # Remove default sheet default_sheet = workbook.active workbook.remove(default_sheet) # Dictionary to store sheet names for index tunnel_sheets = {} # Create sheets for each tunnel for tunnel_name in phase1_configs: try: rows = [] # Phase 1 Configuration for key, value in phase1_configs[tunnel_name].items(): rows.append({"Category": "Phase 1 Configuration", "Field": key, "Value": value}) # Phase 2 Configuration for phase2_name, phase2_data in phase2_configs.items(): if phase2_data.get("Phase 1 Name") == tunnel_name: for key, value in phase2_data.items(): rows.append({"Category": f"Phase 2: {phase2_name}", "Field": key, "Value": value}) # Firewall Policies for policy in firewall_policies.get(tunnel_name, []): for key, value in policy.items(): rows.append({"Category": "Firewall Policy", "Field": key, "Value": value}) # Address Objects (for dial-up VPNs) client_ip_range = phase1_configs[tunnel_name].get("Client IP Range", "N/A") if client_ip_range != "N/A" and client_ip_range in address_objects: for key, value in address_objects[client_ip_range].items(): rows.append({"Category": "Client IP Range", "Field": key, "Value": value}) # Create DataFrame df = pd.DataFrame(rows) # Create sheet with truncated name sheet_name = tunnel_name[:31] # Excel sheet name limit worksheet = workbook.create_sheet(sheet_name) tunnel_sheets[tunnel_name] = sheet_name # Write DataFrame to worksheet using openpyxl # Write headers headers = df.columns.tolist() for col_idx, header in enumerate(headers, 1): worksheet[f"{get_column_letter(col_idx)}1"] = header # Write data for row_idx, row in enumerate(df.itertuples(index=False), 2): for col_idx, value in enumerate(row, 1): worksheet[f"{get_column_letter(col_idx)}{row_idx}"] = str(value) except Exception as e: print(f"Error processing tunnel {tunnel_name}: {e}") # Create index sheet index_sheet = workbook.create_sheet("Index", 0) # Place at the beginning index_sheet.append(["Tunnel Name", "Link"]) # Add hyperlinks to each tunnel sheet row = 2 for tunnel_name, sheet_name in tunnel_sheets.items(): cell = index_sheet[f"A{row}"] cell.value = tunnel_name link_cell = index_sheet[f"B{row}"] # Escape single quotes in sheet name for Excel HYPERLINK formula escaped_sheet_name = sheet_name.replace("'", "''") link_cell.value = f'=HYPERLINK("#\'{escaped_sheet_name}\'!A1", "{sheet_name}")' row += 1 # Save workbook try: workbook.save(output_file) print(f"Excel file created with index sheet: {output_file}") except Exception as e: print(f"Error saving Excel file: {e}") def main(): # Input file config_file = "fortigate_config.conf" # Replace with your config file output_file = "ipsec_tunnels.xlsx" try: # Read config file with open(config_file, "r") as f: config_text = f.read() # Parse configurations phase1_configs = parse_phase1_config(config_text) phase2_configs = parse_phase2_config(config_text) firewall_policies = parse_firewall_policies(config_text, phase1_configs.keys()) address_objects = parse_address_objects(config_text) if not phase1_configs: print("No IPsec tunnels found in the configuration file.") return # Create Excel with index sheet create_excel_from_configs(phase1_configs, phase2_configs, firewall_policies, address_objects, output_file) except FileNotFoundError: print(f"Config file {config_file} not found.") except Exception as e: print(f"Error: {e}") if __name__ == "__main__": main()

Thursday, March 20, 2025

URL testing script and exe using python

the script/exe and URL test file need to be in same folder for it to work the URL should be in format http://abc.com format only https://drive.google.com/drive/folders/1sUsyqpMoS2VWXlKsoE2QTHDmB7iHN77v?usp=drive_link

Wednesday, February 19, 2025

JIO Plans analysis for 19-Feb-2025

Hi, below is the analysis of some of the plans of jio to choose wisely most affordable for you if you are using home WiFi most of the time you dont need daily data packs.

Monday, February 17, 2025

Best portable HDD

This is the best portable compact value for money and rugged external drive you can find https://amzn.to/4hGq0Mn

best travel adaptor in 2025

This is the best and compact travel adapter you can buy in 2025 rts Universal Travel Adapter https://amzn.to/42Vl1TL

Best TWS in 2025

OnePlus Buds 3 Best in class sound ANC works well for calls Noise cancellaton is the best price is a bit high but it matches premium TWS which cost 5 times more build to last https://amzn.to/3QnelGi