MikroTik 802.1x EAP Wi-Fi Authentication using freeRADIUS

This guide walks you through creating certificates on a MikroTik router, configuring FreeRADIUS with a valid SAN, and preparing Android clients for EAP-TLS authentication using radius.mikrotikmasters.com as the domain.


✅ Step 1: Generate Certificates on MikroTik

1. Create a Certificate Authority (CA)

/certificate
add name=cert-ca common-name=MyRootCA key-usage=key-cert-sign,crl-sign
/certificate sign cert-ca ca-crl-host=10.200.21.33

2. Create Server Certificate with SAN

/certificate
add name=cert-server common-name=radius.mikrotikmasters.com \
subject-alt-name=DNS:radius.mikrotikmasters.com \
key-usage=digital-signature,key-encipherment,tls-server
/certificate sign cert-server ca=cert-ca

3. Export the Certificates

/certificate export-certificate cert-ca export-passphrase=""
/certificate export-certificate cert-server export-passphrase=exportpass

Files will appear in the Files section as:

  • cert_export_cert-ca.crt
  • cert_export_cert-server.crt
  • cert_export_cert-server.key

Download them via Winbox, WebFig, or SCP.


✅ Step 2: Install Certificates on FreeRADIUS

1. Move Certificate Files to FreeRADIUS

Run the following commands on your FreeRADIUS server:

sudo mv cert_export_cert-ca.crt /etc/freeradius/3.0/certs/ca.cert
sudo mv cert_export_cert-server.crt /etc/freeradius/3.0/certs/server.crt

2. Decrypt the Server Private Key

If your server key is encrypted, decrypt it:

openssl rsa -in cert_export_cert-server.key -out server.key
sudo mv server.key /etc/freeradius/3.0/certs
/

Then delete the encrypted key file:

rm cert_export_cert-server.key

3. Set Permissions

sudo chown -R freerad:freerad /etc/freeradius/3.0/certs

✅ Step 3: Configure FreeRADIUS EAP Module

Edit /etc/freeradius/3.0/mods-enabled/eap:

tls-config tls-common {
private_key_file = /etc/freeradius/3.0/certs/server.key
certificate_file = /etc/freeradius/3.0/certs/server.crt
ca_file = /etc/freeradius/3.0/certs/ca.cert

dh_file = /etc/freeradius/3.0/certs/dh
random_file = /dev/urandom

fragment_size = 1024
include_length = yes
check_crl = no
}

tls {
tls = tls-common
}

peap {
tls = tls-common
}

ttls {
tls = tls-common
}

Or full config used in Video:

eap {
	default_eap_type = tls
	timer_expire = 60
	ignore_unknown_eap_types = no
	cisco_accounting_username_bug = no
	max_sessions = ${max_requests}
	md5 {
	}
	gtc {
		auth_type = PAP
	}
	tls-config tls-common {
		private_key_file = /etc/freeradius/3.0/certs/server.key
		certificate_file = /etc/freeradius/3.0/certs/server.crt
		ca_file = /etc/freeradius/3.0/certs/ca.crt
		ca_path = ${cadir}
		cipher_list = "DEFAULT"
		cipher_server_preference = yes
		tls_min_version = "1.2"
		tls_max_version = "1.2"
		ecdh_curve = ""
		cache {
			enable = no
			store {
				Tunnel-Private-Group-Id
			}
		}
		verify {
		}
		ocsp {
			enable = no
			override_cert_url = yes
			url = "http://127.0.0.1/ocsp/"
		}
	}
	tls {
		tls = tls-common
	}
	ttls {
		tls = tls-common
		default_eap_type = md5
		copy_request_to_tunnel = no
		use_tunneled_reply = no
		virtual_server = "inner-tunnel"
	}
	peap {
		tls = tls-common
		default_eap_type = mschapv2
		copy_request_to_tunnel = no
		use_tunneled_reply = no
		virtual_server = "inner-tunnel"
	}
	mschapv2 {

	}
}

Then test the config:

sudo freeradius -XC

Start the service:

sudo service freeradius restart

✅ Step 4: Install Certificates on Android (EAP-TLS)

1. Prepare a Client Certificate (Optional if using PEAP)

On MikroTik:

/certificate
add name=cert-client common-name=android-user key-usage=tls-client
/certificate sign cert-client ca=cert-ca
/certificate export-certificate cert-client type=pkcs12 export-passphrase=androidpass

This generates a .p12 file for Android.


2. Install Certificates on Android

  • Install ca.cert as a trusted CA certificate.
  • Import cert-client.p12 (if using EAP-TLS) with androidpass.

3. Wi-Fi EAP Settings

When connecting to the MikroTik SSID:

  • EAP Method: TLS or PEAP
  • CA Certificate: Use installed CA
  • Domain: radius.mikrotikmasters.com
  • Identity: android-user (for TLS)
  • User Certificate: Select the installed client certificate (for TLS)
  • Password: (Only for PEAP + MSCHAPv2)

⚠️ On Android 11+, the domain must exactly match the SAN (DNS:radius.mikrotikmasters.com) in the server certificate.


✅ Step 5: Monitor FreeRADIUS Logs

sudo freeradius -X

Try connecting from Android and watch for TLS negotiation and authentication success.


✅ Reference: Key Commands History

Here are the relevant shell commands used to manage files and permissions:

sudo mv cert_export_cert-ca.crt /etc/freeradius/3.0/certs/ca.cert
sudo mv cert_export_cert-server.crt /etc/freeradius/3.0/certs/server.crt
openssl rsa -in cert_export_cert-server.key -out server.key
sudo mv server.key /etc/freeradius/3.0/certs/
sudo chown -R freerad:freerad /etc/freeradius/3.0/certs/
sudo nano /etc/freeradius/3.0/mods-enabled/eap
sudo freeradius -XC
sudo freeradius -X

Optional

Full SQL Mods Enabled config file used in Video

sql {
	dialect = "mysql"
	driver = "rlm_sql_${dialect}"
	sqlite {
		filename = "/tmp/freeradius.db"
		busy_timeout = 200
		bootstrap = "${modconfdir}/${..:name}/main/sqlite/schema.sql"
	}
	mysql {
		warnings = auto
	}
	postgresql {
		send_application_name = yes
	}
	mongo {
		appname = "freeradius"
		tls {
			certificate_file = /path/to/file
			certificate_password = "password"
			ca_file = /path/to/file
			ca_dir = /path/to/directory
			crl_file = /path/to/file
			weak_cert_validation = false
			allow_invalid_hostname = false
		}
	}

	server = "localhost"
	port = 3306
	login = "radius"
	password = "helloworld123"

	radius_db = "radius"

	acct_table1 = "radacct"
	acct_table2 = "radacct"

	postauth_table = "radpostauth"

	authcheck_table = "radcheck"
	groupcheck_table = "radgroupcheck"

	authreply_table = "radreply"
	groupreply_table = "radgroupreply"

	usergroup_table = "radusergroup"

	delete_stale_sessions = yes

	pool {
		start = ${thread[pool].start_servers}
		min = ${thread[pool].min_spare_servers}
		max = ${thread[pool].max_servers}
		spare = ${thread[pool].max_spare_servers}
		uses = 0
		retry_delay = 30
		lifetime = 0
		idle_timeout = 60
	}
	read_clients = yes
	client_table = "nas"
	group_attribute = "SQL-Group"

	$INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf
}

Leave a Comment

Your email address will not be published. Required fields are marked *