🤕 clumsy.dev 🚀

Check for iCloud Private Relay

cloudflare workersheaders

This is just a simple Worker reading the request.cf object from Workers to check if the ASN is reported back as iCloud Private Relay. I used this mostly during the beta phase of iCloud Private Relay to check if it was working or not.

A very simple demo site is available here, or just copy and paste the code below into a new worker.

Open Source Code
addEventListener('fetch', (event) => {
  event.respondWith(handleRequest(event.request))
})

function getHeaders(request) {
  let cfHeaders = request.cf
  let headers = Object.fromEntries(request.headers)

  let allHeaders = { ...cfHeaders, ...headers }
  let output = { ip: allHeaders['cf-connecting-ip'], asOrg: allHeaders['asOrganization'] }

  return output
}

function checkPrivateRelay(request) {
  if (request === 'iCloud Private Relay') {
    return true
  }
  return false
}

async function handleRequest(request) {
  let header = getHeaders(request)
  let iCloud = checkPrivateRelay(header.asOrg)
  let output = JSON.stringify({ icloud: iCloud, reported_ip: header.ip }, null, 2)

  let { searchParams } = new URL(request.url)
  let format = searchParams.get('format')

  if (format === 'json') {
    return new Response(output, { headers: { 'content-type': 'application/json' } })
  }

  let outString = `<!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Check iCloud Private Relay</title>
      <style>
        body{font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, roboto, noto, arial, sans-serif;}.box {display: flex;align-items: center;justify-content: center;}.green{background-color:green }.red{background-color:red }
      </style>
  </head>
  <body class="${iCloud ? 'green' : 'red'}">
      <div class="box">
        <p>
          iCloud Private Relay: ${iCloud ? '✅' : '❎'}
          <br>
          Reported IP: ${header.ip}
        </p>
      </div>
  </body>
  </html>`

  return new Response(outString, {
    headers: { 'content-type': 'text/html; charset=UTF-8' },
  })
}