Guest User!

You are not Sophos Staff.

[FEATURE REQUEST] [7.400] Way to generate openvpn apc file for non astaro server

Hi

Do you plan to release a tool to generate openvpn .apc file so we can use openvpn client with non astaro openvpn servers ?

thx
  • Hi,

    I'd like to have such a tool too! Vice-versa (Astaro acting as OpenVPN Server, converting the client .apc to ca.crt, client.crt, client.key and client.ovpn, like the Remote Access SSL-Client config files)
    A little commandline tool would suffice, or implement it as a Webinterface-function
    Kind Regards,
    Patrick
  • Hello all,

    I was trying to create a .apc file from my OpenVPN config files.
    This is what I found out so far:
    The .apc is a Text/Hex file, which is using some Hex-codes for determining the length of different options (I guess...)
    It consists of some options (usually found in the .ovpn/.conf found), the client.cert, the ca.cert, the client.key, followed by some other options.
    The third hexvalue 0x04 seems to define the lenght of the next textfield "1234"
    the 0x03 in front of the "tcp" seems to do the same. "protocol" is 8 characters, which could be indicated by the 0x08, although it looks a little strange, because there are three 0x00 following the 0x08. The three/two 0x00 could be indicating that this is an option, not a value.
    "0x0a" = New line
    The header seems to be either constant or some kind of checksum

    0x04 0x06 0x04 1234 0x04 0x04 0x04 0x08 0x03 0x0C 0x00 0x00 0x00 0x0d 0x0a
    0x03 tcp 0x08 0x00 0x00 0x00 protocol 0x0d 0x0a
    0x03 MD5 0x18 0x00 0x00 0x00 authentication_algorithm 0x01 0x49 0x0e 0x00 0x00  0x0a 
    0x0b 0x00 0x00 0x00 certificate 0x01 0x77 0x0c 0x00 0x00  0x0a
    0x07 0x00 0x00 0x00 ca_cert 0x01 0x77 0x03 0x00 0x00  0x0a
    0x03 0x00 0x00 0x00 key 0x0a
    0x0e REF_1234567890 0x08 0x00 0x00 0x00 username 0x08 0x81 0x0b 0x00 0x00 compression 0x0a 
    0x0b AES-128-CBC 0x14 0x00 0x00 0x00 encryption_algorithm 0x0a
    0x20 1234567890123456789012 0x08 0x00 0x00 0x00 password 0x0a
    0x61 /C=country/L=Town/O=Organization/CN=hostname/emailAddress=me@my.org 0x09 0x00 0x00 0x00 server_dn 0x0a
    0x03 443 0x0b 0x00 0x00 0x00 server_port 0x0a
    0x08 astaro01 0x0e 0x00 0x00 0x00 server_address 0x00

    I couldn't interpret the hexvalues in front of the certificates and the keys:
    0x01 0x49 0x0e 0x00 0x00  client.crt is 3657 bytes
    0x01 0x6A 0x0c 0x00 0x00  ca.crt is 3178 bytes 
    0x01 0x77 0x03 0x00 0x00  client.key is 887 bytes.

    Update: Found out the meanings:
    3657 dec  = 0x0e49 hex => switch byte order  0x49 0x0e
    3178 dec = 0x0c6a hex => switch byte order 0x6a 0x0c
    887 dec = 0x0377 hex => switch byte order 0x77 0x03

    I'll try to create a .apc from my config files and report back later.

    Kind Regards,
    Patrick
  • Hello all,

    I just wanted to confirm that the format described in my last post is correct and working!
    Maybe I'll write a small shell script which does the job automatically.

    Kind regards,
    Patrick

    EDIT:
    Just finished hacking a little bash script to convert an openvpn-configuration to an Astaro .apc file
    Not pretty, not fool-proof, but it is working for me so far.
    Filename: ovpn-to-apc

    #!/bin/bash
    # $1 : OpenVPN Config File
    # $2 : Astaro .apc to create
    # $3 : username
    # $4 : password

    if [ $# -lt 2 ] || [ $# -gt 4 ]
    then
      echo
      echo Usage:
      echo ${0} openvpn-config.ovpn  output.apc [username] [password]
      echo username and password are optional and may be entered by the user
      echo The config file needs to contain the ca, cert and key directives
      echo that point to the corresponding files. 
      exit
    fi
    if [ $# -gt 2 ] && [ $# -lt 4 ] # username only
    then
      user=${3}
      echo "Please enter your password: "
      read pass
    elif [ $# -gt 3 ] # username and password
    then
      user=${3}
      pass=${4}
    else # read username and password from commandline
      user=`echo $1 | cut -d '@' -f1`
      if [ ${user} = ${1} ]
      then
        echo "Enter username: "
        read user
      fi
      echo "Please enter your password: "
      read pass
    fi

    # Read the filenames from the config-file
    ca=`grep "^ca " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    key=`grep "^key " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    cert=`grep "^cert " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    # Write .apc header
    printf "\x04\x06\x041234\x04\x04\x04\x08\x03\x0c\x00\x00\x00\x0a" > $2
    # Extract protocol (UDP/TCP) from config file
    var=`grep "^proto " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    # Determine length of the protocol and convert it to hex
    varlen=`echo ${var} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    # Write length to output file
    printf "\x${varlen}" >> ${2}
    # Write protocol to output file
    echo $var | tr -d '\n' >> ${2}
    # Write fix information to output file 
    printf "\x08\x00\x00\x00" >> ${2}
    echo protocol >>${2}

    # And so on...
    var=`grep "^auth " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    varlen=`echo ${var} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    printf "\x${varlen}" >> ${2}
    echo $var | tr -d '\n' >> ${2}
    printf "\x18\x00\x00\x00" >> ${2}
    echo authentication_algorithm | tr -d '\n' >> ${2}

    # Determine length of certifcate file
    varlen=`cat ${cert} | wc -c` # Length decimal
    hex=`echo "obase=16; ${varlen}" | bc -q`   # Lengthe hexadecimal
    num=`echo "obase=16; ${varlen}" | bc -q | tr -d '\n' | wc -c` # Length of the hex-number
    odd=`expr ${num} % 2` # hex-number: even or odd?
    # TODO: Add a check for bigger hex-number (more than 4 digits)
    if [ ${odd} -eq 0 ] 
    then  # even: swap AABB > BBAA
      varlen1=`echo "obase=16; ${varlen}" | bc -q | cut -b 3,4`
      varlen2=`echo "obase=16; ${varlen}" | bc -q | cut -b 1,2`
    else  # odd: swap AAB > AB 0A
      varlen1=`echo "obase=16; ${varlen}" | bc -q | cut -b 2,3`
      varlen2=`echo "obase=16; ${varlen}" | bc -q | cut -b 1`
    fi

    printf "\x1\x${varlen1}\x${varlen2}\x0\x0" >> ${2} 
    cat ${cert} >> ${2}
    printf "\xb\x0\x0\x0" >> ${2}
    echo "certificate" | tr -d '\n' >> ${2}


    varlen=`cat ${ca} | wc -c`
    hex=`echo "obase=16; ${varlen}" | bc -q`
    num=`echo "obase=16; ${varlen}" | bc -q | tr -d '\n' | wc -c`
    odd=`expr ${num} % 2`
    if [ ${odd} -eq 0 ]
    then
      varlen1=`echo "obase=16; ${varlen}" | bc -q | cut -b 3,4`
      varlen2=`echo "obase=16; ${varlen}" | bc -q | cut -b 1,2`
    else
      varlen1=`echo "obase=16; ${varlen}" | bc -q | cut -b 2,3`
      varlen2=`echo "obase=16; ${varlen}" | bc -q | cut -b 1`
    fi

    printf "\x1\x${varlen1}\x${varlen2}\x0\x0" >> ${2}
    cat ${ca} >> ${2}

    printf "\x7\x0\x0\x0" >> ${2}
    echo "ca_cert" | tr -d '\n' >> ${2}

    varlen=`cat ${key} | wc -c`
    hex=`echo "obase=16; ${varlen}" | bc -q`
    num=`echo "obase=16; ${varlen}" | bc -q | tr -d '\n' | wc -c`
    odd=`expr ${num} % 2`
    if [ ${odd} -eq 0 ]
    then
      varlen1=`echo "obase=16; ${varlen}" | bc -q | cut -b 3,4`
      varlen2=`echo "obase=16; ${varlen}" | bc -q | cut -b 1,2`
    else
      varlen1=`echo "obase=16; ${varlen}" | bc -q | cut -b 2,3`
      varlen2=`echo "obase=16; ${varlen}" | bc -q | cut -b 1`
    fi

    printf "\x1\x${varlen1}\x${varlen2}\x0\x0" >> ${2}
    cat ${key} >> ${2}

    printf "\x3\x0\x0\x0" >> ${2}
    echo "key" >> ${2}

    varlen=`echo ${user} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    printf "\x${varlen}" >>${2}
    echo ${user} | tr -d '\n' >> ${2}

    printf "\x08\x00\x00\x00" >> ${2}
    echo username | tr -d '\n' >> ${2}


    var=`grep "^comp-lzo" ${1}|tr -d '\n'`
    if [ ${var} = "comp-lzo" ]
    then
      printf "\x0a\x01\x31\x0b\x0\x0\x0" >> ${2}
    else
      printf "\x0a\x01\x31\x0b\x0\x0\x0" >> ${2}
    fi
    echo compression >> ${2}

    var=`grep "^cipher " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    varlen=`echo ${var} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    printf "\x${varlen}" >> ${2}
    echo $var | tr -d '\n' >>${2}
    printf "\x14\x00\x00\x00" >> ${2}

    echo encryption_algorithm >> ${2}

    varlen=`echo ${pass} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    printf "\x${varlen}" >> ${2}
    echo ${pass} | tr -d '\n' >> ${2}
    printf "\x08\x00\x00\x00" >> ${2}
    echo password >> ${2}

    var=`grep "^tls-remote " ${1} | cut -d '"' -f2 |tr -d '\n'`
    temp=`echo ${var} | grep "^tls-remote "`
    if [ "${temp}" = "${var}" ]
    then
      var=`grep "^tls-remote " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    fi
    varlen=`echo ${var} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    printf "\x${varlen}" >> ${2}
    echo $var | tr -d '\n' >> ${2}
    printf "\x09\x00\x00\x00" >> ${2}
    echo server_dn >> ${2}

    var=`grep "^remote " ${1} | cut -d ' ' -f3 |tr -d '\n'`
    varlen=`echo ${var} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    printf "\x${varlen}" >> ${2}
    echo $var | tr -d '\n' >>${2}
    printf "\x0b\x00\x00\x00" >> ${2}
    echo server_port >> ${2}

    var=`grep "^remote " ${1} | cut -d ' ' -f2 |tr -d '\n'`
    varlen=`echo ${var} | tr -d '\n' | wc -c`
    varlen=`echo "obase=16; ${varlen}" | bc -q`
    printf "\x${varlen}" >> ${2}
    echo $var | tr -d '\n' >> ${2}
    printf "\x0e\x00\x00\x00" >> ${2}
    echo server_address| tr -d '\n' >> ${2}