Skip to content

Instantly share code, notes, and snippets.

@crrapi
Created August 27, 2024 02:33
Show Gist options
  • Save crrapi/cdd9eb6e859160bd74ed53d2c7d8ec04 to your computer and use it in GitHub Desktop.
Save crrapi/cdd9eb6e859160bd74ed53d2c7d8ec04 to your computer and use it in GitHub Desktop.
wireguard-mobileconfig-gen.py
import uuid
import plistlib
import argparse
import os
def generate_mobileconfig(wg_conf_path, platform="ios", profile_name="WireGuard Demo Configuration Profile", identifier="com.your-org.wireguard"):
# Generate UUIDs for the payloads
profile_uuid = str(uuid.uuid4()).upper()
vpn_uuid = str(uuid.uuid4()).upper()
# Read the WireGuard configuration file
with open(wg_conf_path, 'r') as f:
wg_conf = f.read()
# Extract RemoteAddress from the Peer section in the WireGuard config
remote_address = None
for line in wg_conf.splitlines():
if line.strip().startswith('Endpoint ='):
remote_address = line.split('=')[1].strip()
break
if not remote_address:
raise ValueError("RemoteAddress (Endpoint) not found in the WireGuard configuration file.")
# Set the VPNSubType based on the platform
vpn_subtype = f"com.wireguard.{platform}"
# Create the WireGuard VPN payload
vpn_payload = {
"PayloadDisplayName": "VPN",
"PayloadType": "com.apple.vpn.managed",
"PayloadVersion": 1,
"PayloadIdentifier": f"{identifier}.demo-profile-1.demo-tunnel",
"PayloadUUID": vpn_uuid,
"UserDefinedName": "Demo from MobileConfig file",
"VPNType": "VPN",
"VPNSubType": vpn_subtype,
"VendorConfig": {
"WgQuickConfig": wg_conf
},
"VPN": {
"RemoteAddress": remote_address,
"AuthenticationMethod": "Password"
}
}
# Create the top-level profile dictionary
profile_payload = {
"PayloadDisplayName": profile_name,
"PayloadType": "Configuration",
"PayloadVersion": 1,
"PayloadIdentifier": f"{identifier}.{profile_uuid}",
"PayloadUUID": profile_uuid,
"PayloadContent": [vpn_payload]
}
# Convert to plist XML format
plist_data = plistlib.dumps(profile_payload, fmt=plistlib.FMT_XML)
# Write to a .mobileconfig file
mobileconfig_path = wg_conf_path.replace('.conf', '.mobileconfig')
with open(mobileconfig_path, 'wb') as f:
f.write(plist_data)
print(f"MobileConfig generated: {mobileconfig_path}")
def main():
parser = argparse.ArgumentParser(description="Generate a .mobileconfig file from a WireGuard .conf file.")
parser.add_argument("config_file", help="Path to the WireGuard .conf file")
parser.add_argument("--platform", choices=["ios", "macos"], default="ios", help="Target platform for the configuration profile (ios or macos)")
parser.add_argument("--profile-name", default="WireGuard Demo Configuration Profile", help="Name of the configuration profile")
parser.add_argument("--identifier", default="com.your-org.wireguard", help="Reverse-DNS style unique identifier for the profile")
args = parser.parse_args()
if not os.path.isfile(args.config_file):
print(f"Error: The file {args.config_file} does not exist.")
return
generate_mobileconfig(
wg_conf_path=args.config_file,
platform=args.platform,
profile_name=args.profile_name,
identifier=args.identifier
)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment