More and more products are “smart” - or trying to be, with always-on mobile app connections to the cloud. Yet many apps expose no API and send your telemetry or health metrics straight to their cloud. Even after politely asking the vendor, you may be offered neither an API nor a data export, often citing “internal business secrets”.
That raised two questions for me: What sensitive data is my phone actually sending about me that qualifies as a “business secret”? And how can I automatically capture my own copy of that data in my database, redact sensitive fields in transit (e.g., names, email, precise location) before they ever leave my phone?
The answer is simple: be your own man-in-the-middle (MITM)
Disclaimer: The techniques described here involve intercepting and modifying network traffic. Use them only on devices, accounts, and networks you own and control, and only with explicit permission. Unauthorized interception may violate privacy and communications laws in your jurisdiction. Always comply with applicable laws and obtain any required consents before implementing any form of traffic interception or modification.
Architecture
The architecture consists of several key components:
Device Trust: iOS is configured to trust my root Certificate Authority (CA) (installed via configuration profile, then explicitly enabled under Settings -> General -> About -> Certificate Trust Settings). Apple documents the manual trust toggle for user-installed roots.
Routing: AdGuard Home uses rewrite rules for a curated allowlist of domains (e.g., api.fitness-app.example) to a local VM (“inspection host”). Everything else resolves normally (no interception).
Inspection Host: A Go service acting as a TLS‐terminating reverse proxy:
- Terminates TLS with an on-the-fly issued leaf from my private CA (per hostname).
- Opens a new upstream TLS connection to the original host.
- Runs a filter pipeline per route to log -> normalize -> redact -> forward.
Data Sink: Redacted copies are submitted to other internal systems using REST APIs. There, additional systems process the data into their needed formats (e.g., MySQL, call to HYNC.io API, …) with schemas per app.
Safety Rails by Default:
- Allowlist-only interception (no wildcards).
- Header & body redaction with irreversible hashing for emails/IDs.
- Short-lived (25 hours) certificate per domain; the CA private key stored offline and was never saved on the same host; proxy uses intermediate CA to issue leaf certs.
- Audit: Every interception decision is logged with policy rationale.
Threat Model
Data Exposure: While I control the interception, there’s still a risk of exposing sensitive data if the system is compromised or if data is not correctly redacted in transit. This includes both the raw data and the redacted versions.
Legal Risks: Depending on jurisdiction, intercepting and modifying traffic - even for personal use - could have legal implications. I ensure compliance with all relevant laws and regulations and only intercept my own traffic.
Technical Risks: The system relies on several components (AdGuard Home, the inspection host, etc.), each of which could fail or be misconfigured. I maintain backups and redundancy to mitigate this.
Goal: Exfiltrate my own data for my own use from closed apps or minimize what leaves my phone.
Non-goal: Attacking third parties, evading app certificate pinning, or weakening security on shared networks.
Residual risk: A rogue CA is dangerous. If someone gets your CA key, they can MITM you. Counter: short validity, no reuse, strict key custody, allowlist scope, and alerting.
My use cases
As previously mentioned, many apps don’t offer APIs or data exports. My main and primary use cases are:
Body Scale Apps: My weight scale is connected via Bluetooth to my phone, which uploads data to the vendor’s cloud. Here I can capture my weight, body fat, fat-free mass, body water, muscle mass, soft/lean mass, bone mass, and BMI.
Blood Pressure Monitors: Similar to the scale, my blood pressure monitor syncs via Bluetooth and uploads systolic/diastolic blood pressure, heart rate, and measurement timestamps.
Calorie/Nutrition Trackers: Most apps do not offer APIs. I capture food entries, amount, nutritional information (calories, macronutrients), meal times, and user notes.
Insight into App Behavior: By intercepting traffic, I can understand what data the app collects and transmits, helping me make informed decisions about my privacy. Does the app send more data than I expect? Are there any unexpected third-party trackers?
Data Redaction: I can redact or randomize sensitive information such as device identifiers, precise location data, and health metrics before it leaves my device, enhancing my privacy. In most cases, I can simply drop the entire request. (I don’t see the need why Sentry - a crash reporting tool - should know my geolocation + name + email + device serial number + weight with each successful record added on my scale app.)
All data is generalized into a common schema and needed data points are extracted. I can then run my own analytics, visualize trends, and integrate this data with other health metrics I track. This also allows me to maintain a historical record independent of the app vendor, which is useful if they change their service or go out of business.
Additionally through manipulating the data in transit, I can enrich the data in an automated way. After recording a weight measurement, the weight measurement is not only stored in my DB, but also sent to my calorie tracker app as a new weight entry. This way I can keep my weight in sync across multiple apps without manual input.
Combination of tools allows the best of both worlds: A weight entry recorded from my scale app is captured by my MITM proxy, redacted, and stored in my DB. The action triggers a REST request to an internal webhook service. This webhook service processes the new weight entry and formats it for the calorie tracker app’s API or other health platforms I use - like to update the current weight record in Strava which is set via their official API. This way I can keep my weight and other measurement data in sync across multiple apps without manual input.
Besides health data, other use cases include:
Bringing the dead back to life: Some apps have been abandoned by their developers and no longer function, the companies or services have shut down, or the APIs have changed. I can sometimes restore functionality by intercepting and modifying the traffic. For example, an app that used to sync with a now-defunct cloud service might still work if I redirect the requests to a local server that mimics the legacy API. - This is more of a hobbyist use case, but it can be fun and rewarding. Especially this is a good way to reduce e-waste by keeping old devices and apps functional.
Facebook/Meta: Capture and redact telemetry data sent by the Facebook SDK, such as usage patterns, interaction data, and device information. At the same time, passing legitimate traffic (e.g., avatar images, posts) unmodified.
Local food service app: In my area, there’s a local food app that shows the daily menu of nearby canteens. The data in the app changes very frequently and without any notice. By intercepting the traffic, I got an overview of the API calls and can now scrape the daily menu automatically every morning and send it to a Microsoft Teams channel.
Company credit card for food: My company provides a credit card for food delivery services. The app used to manage the card has no API and no data export. By intercepting the traffic, I can capture current balance, transaction history, amounts, merchant details, and timestamps. (This is not a custom made app, but a standard app used by many companies in Austria. It was very surprising for me that such an app does not use certificate pinning. It even provides the actual credit card number, CVV, expiry date, and PIN to unlock the fields in the app in a single API response.)
Local gym app: My gym has an app to manage memberships, bookings, and classes. Using their internal API, I can capture the utilization of the gym, my bookings, class schedules, and membership status. This allows me to analyze my workout patterns, make automatic bookings, and get reminders for upcoming classes.
Desk booking app: In my company, we use a desk booking app to manage our office space. The app has no API and no data export options. By intercepting the traffic, I can capture desk bookings, my reservations, and occupancy. This allows me to automatically remind myself if I have a desk and parking space booked for the next day or week.
Basic implementation
Below is a high-level overview of how I implemented my personal MITM proxy in Go, focusing on the key components and safety measures. This is not a complete tutorial but rather a guide to the architecture and considerations involved.
As shown in the diagram, the flow of a request is as follows:
- The client device (iOS) performs a DNS lookup for a specific domain (e.g., api.fitness-app.example). AdGuard Home intercepts this request and rewrites it to point to the inspection host (the MITM proxy).
- The client device initiates a TLS connection (HTTPS) to the inspection host. The inspection host generates the certificate on-the-fly and presents its certificate to the client. The client verifies the certificate and establishes a secure connection.
- The inspection performs a DNS lookup for the original domain (api.fitness-app.example) to get its real IP address.
- The inspection host establishes a new TLS connection to the original server using the real IP address. It verifies the server’s certificate to ensure it’s connecting to the legitimate server.
- The inspection host inspects, logs, and potentially modifies the request before forwarding it to the original server.
- The original server processes the request and sends back a response.
- The inspection host inspects, logs, and potentially modifies the response before sending it back to the client device.
- The processed request and response are forwarded to the internal REST API service for further processing and storage.
The first step is to set up a reverse proxy that can handle incoming HTTPS requests, terminate TLS, and forward the requests to the intended destination. As incoming and outgoing traffic is to be manipulated, a custom reverse proxy implementation is needed.
|
|
As in the example above, the proxy listens on both HTTP (port 80) and HTTPS (port 443). All incoming requests are handled by the same function, which extracts the domain from the request and forwards it to the appropriate reverse proxy instance. HTTP is used additionally as some apps may still use plaintext HTTP for certain requests.
The proxy.Serve
and proxy.CreateProxy
function is where the core logic begins. It involves several steps:
- Locking the proxy storage to ensure thread safety.
- Checking if there is an incoming request handler for the domain and executing it if present.
- Logging the request if logging is enabled for the domain.
- Serving the request using the appropriate reverse proxy.
- Creating a new reverse proxy for a domain if it doesn’t already exist, with optional request logging.
- Binding the modification function to the proxy to handle response modifications.
- Setting up the transport layer with appropriate timeouts and dial context.
|
|
With all functionality set up, before starting the web server the routines for each domain are created. For example, to create a proxy for api.fitness-app.example
with request logging enabled and a custom modification function:
|
|
By default, every request is passed through unmodified. Only requests where a modification function is set are intercepted and processed. To simplify the implementation, here is an example modification function that extracts the payload from a fitness app’s API response to be forwarded to an internal webhook service for further processing:
|
|
The requestGetBody
function reads and restores the request body, allowing it to be read multiple times if necessary.
Using this setup, I can selectively intercept and manipulate traffic from specific apps, manipulate the data as needed, and forward it to my internal systems for storage and analysis. The modular design allows for easy addition of new apps and modification functions as needed.
Limitations & gotchas
There are several limitations and considerations to keep in mind when implementing a personal MITM proxy:
Certificate pinning: Many iOS & Android apps, especially higher-security apps (e.g., banking) pin their certs, so your proxy won’t see plaintext. That’s expected and a very good thing as this also limits other MITM proxies like some used in enterprise environments. Don’t attempt to tamper with binaries or trust stores.
Android: Android is more restrictive with user-installed CAs in recent versions. You may need to configure per-app network security config, the developer needs to allow user CAs, or you need to use a rooted device to inject your CA into the system store.
Breakage risk: Even with careful transforms, you might trigger fraud/abuse detectors if you change semantics. Keep in mind that nearly every app vendor has a “terms of service” that may prohibit interception or modification of traffic. If something is detected, you may be locked out of your account or worse. Always check the terms of service and ensure compliance.
For my own privacy and safety, I strip out or redact sensitive fields in transit. This minimizes the risk of exposing sensitive data if the system is compromised or if data is not correctly redacted in transit. Especially location data, a weight tracking app doesn’t need to know my precise GPS coordinates with each weight entry. I usually drop the entire request or replace it with a fake location - like in the middle of the island “Bauminsel” in Neusiedler See, Austria (47.893252, 16.834275).
Legal & Ethical Considerations
When implementing a personal MITM proxy, it’s crucial to consider the legal and ethical implications. This is the condensed, engineer-friendly view - not legal advice. Always check your specific situation with counsel.
Confidentiality of communications (EU ePrivacy Directive, Article 5)
EU law requires Member States to ensure the confidentiality of communications and related traffic data. Intentional interception without consent is generally prohibited, with narrow exceptions (e.g., lawful interception).
Austria: Criminal provisions on interception
§ 119 StGB - Verletzung des Telekommunikationsgeheimnisses: Unauthorized interception of a message transmitted via telecommunications or a computer system can be punishable (generally up to two years). Key elements: message not intended for you, and use of a device attached or made receptive to the system. Prosecution typically requires the injured party’s authorization (§ 119 Abs. 2).
§ 119a StGB - Missbräuchliches Abfangen von Daten: Punishes interception of data transmitted via a computer system when you aim to gain knowledge of data not intended for you and cause benefit or harm, using a device attached/made receptive or by capturing electromagnetic emissions (up to two years).
Intercepting your own device and your own account traffic to services you use and for data about you, within your own network, is the narrow scenario that avoids the “not intended for you” element. The moment you capture other persons’ communications (e.g., guests on your Wi-Fi) or someone else’s account, you risk violating §§ 119/119a. (That includes “curiosity” captures.)
Running such tooling on shared networks or for third-party devices without clear, prior, informed consent is a bad idea legally and ethically. In some cases, consent of all affected parties is expected to be safe.
GDPR (if personal data is stored/processed)
If you store any personal data (yours or others’) you need a legal basis (Art. 6 GDPR) and must respect data minimization (Art. 5(1)(c)), purpose limitation, retention limits, and security of processing. For your own data, this is usually straightforward; for any third-party data, it isn’t.
Telecommunications Act 2021 (TKG 2021) context
The TKG frames definitions and duties for communications networks/services in Austria; while a private LAN isn’t a public provider, its regime underlines the general policy of communications confidentiality and lawful handling. Don’t operate anything resembling a public interception service.
Bottom line: Keep it strictly personal, opt-in, and scoped. Never intercept communications not intended for you. When in doubt, don’t log. These boundaries are not just legal but ethical: Respecting others’ privacy is paramount.
Conclusion
In this post, I outlined my approach to setting up a personal MITM proxy for selectively intercepting and manipulating traffic from specific apps. By leveraging Go’s powerful httputil
package, I can create a modular and extensible proxy solution that meets my needs for automation and data processing.
A selective, well-scoped personal MITM can be a powerful privacy tool: you gain insight into your own data and can reduce what you leak. The trick is to combine strong engineering hygiene with strict legal/ethical boundaries. If any part of your use case drifts beyond your own communications, stop and seek proper alternatives (official exports, subject access requests, or vendor APIs).
At the same time, it’s very interesting to see how vendors implement their apps, what data they collect, and how they communicate. This can inform your choices about which apps to trust and use. I have found several surprising behaviors and data leaks in apps I previously trusted - like a list of all registered users which includes email addresses, names, location data, and hashed passwords being sent in API response to the fitness app. (I reported this to the vendor, but they never replied. I deleted all records I received and stopped using the app.)
Why isn’t the entire code here?
The full implementation involves several components, including request logging, data redaction, and integration with internal APIs, which are beyond the scope of a single post. However, the provided code snippets illustrate the core concepts and structure of the proxy. All key functionalities are demonstrated, and the modular design allows for easy extension and customization. I do not publish the full code to avoid misuse or legal issues.