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
Subscribe to:
Posts (Atom)