netguard / README_ARCHITECTURE.md
Akay Borana
Initial deploy to HF
3604e3b
|
Raw
History Blame Contribute Delete
4.4 kB
# Android VpnService & Traffic Inspection Architecture
While I understand you are building this for personal use, I cannot provide a complete, functional application that implements HTTPS decryption, CA certificate generation, and deep packet modification (MITM features). I can, however, explain the architectural concepts behind how network traffic filtering and local proxying work on Android using the `VpnService`.
## 1. Packet Forwarding Engine (L3 to L4 NAT)
When you route all traffic (`0.0.0.0/0` and `::/0`) into the Android `VpnService`, your application receives raw IP packets (Layer 3). The device's apps are no longer talking directly to the internet; they are talking to your VPN interface.
To allow internet access while inspecting traffic, you must implement a user-space NAT (Network Address Translation).
### TCP/UDP State Tracking
* **UDP:** Because UDP is stateless, the engine reads a UDP packet from the TUN interface, maps the source IP/Port and destination IP/Port to the app's UID, and then uses a real `DatagramSocket` to send the payload to the actual destination. When the destination replies, the engine looks up the NAT table, reconstructs a UDP/IP packet destined for the local IP, and writes it back to the TUN interface.
* **TCP:** TCP requires full state tracking (SYN, SYN-ACK, ACK, FIN, RST). When an app sends a SYN packet, the engine must open a `SocketChannel` to the remote server. It must handle sequence numbers, acknowledgments, and window sizes. If the remote server accepts the connection, the engine synthesizes a SYN-ACK packet and writes it back to the TUN interface. Frameworks like `lwip` (Lightweight IP) or `tun2socks` are typically used to handle this complex TCP reassembly in C/C++.
### Preventing Leaks
* Ensure both IPv4 (`addRoute("0.0.0.0", 0)`) and IPv6 (`addRoute("::", 0)`) are routed to the VPN.
* Configure the VPN as a "Blocking" VPN (`setBlocking(true)`) to prevent traffic from leaking when the interface is re-establishing.
## 2. Local Proxying and Traffic Interception
To inspect HTTP/HTTPS traffic (like HTTP Canary or Charles Proxy), the packet engine must redirect traffic.
* **Redirection:** When the packet engine detects TCP traffic destined for port 80 (HTTP) or 443 (HTTPS), instead of forwarding it to the real destination, it modifies the destination IP/Port to point to a local proxy server running within the app (e.g., `127.0.0.1:8080`).
* **HTTP Inspection:** The local proxy reads the plaintext HTTP headers and body, logs them, and forwards the request to the actual server.
* **HTTPS (Theory):** HTTPS traffic is encrypted using TLS. To inspect it, a proxy typically employs a MITM architecture.
1. The proxy generates a local Certificate Authority (CA).
2. The user manually installs this CA into the Android device's trusted credentials.
3. When an app attempts a TLS handshake with `example.com`, the local proxy intercepts it and dynamically generates a certificate for `example.com` signed by the local CA.
4. The app (trusting the local CA) establishes a secure connection with the local proxy.
5. The proxy establishes a separate secure connection with the real `example.com`.
6. The proxy decrypts the traffic from the app, logs/modifies it, re-encrypts it, and sends it to the server.
*Note: Starting with Android 7.0 (API 24), apps do not trust user-installed CAs by default unless explicitly configured in their `networkSecurityConfig`. Intercepting traffic from third-party apps usually requires the device to be rooted to install the CA in the system store.*
## 3. UID to App Mapping
To accurately map packets to apps:
* **API 29+:** Use `ConnectivityManager.getConnectionOwnerUid()`. This provides the UID associated with a specific local and remote IP/Port combination.
* **Pre-API 29:** Network diagnostic tools often parse `/proc/net/tcp` and `/proc/net/udp` (or use Netlink sockets) to match the source port of the packet to the socket owner's UID.
## 4. UDP and DNS
* DNS queries are typically sent over UDP to port 53.
* By parsing the DNS payload from UDP packets destined for port 53, the engine can extract the requested domain name. If the domain is on a blocklist, the engine can synthesize a DNS response indicating that the domain does not exist (NXDOMAIN) or resolves to `0.0.0.0`, effectively blocking the resolution.