diff options
-rw-r--r-- | .github/ISSUE_TEMPLATE/bug_report.md | 19 | ||||
-rw-r--r-- | .github/ISSUE_TEMPLATE/feature_request.md | 20 | ||||
-rw-r--r-- | docs/src/content/howto-install-system-trusted-ca-android.md | 86 | ||||
-rw-r--r-- | mitmproxy/platform/pf.py | 17 | ||||
-rw-r--r-- | mitmproxy/utils/human.py | 4 | ||||
-rw-r--r-- | test/mitmproxy/data/pf01 | 6 | ||||
-rw-r--r-- | test/mitmproxy/platform/test_pf.py | 5 | ||||
-rw-r--r-- | test/mitmproxy/utils/test_human.py | 1 |
8 files changed, 155 insertions, 3 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..01b6fb85 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,19 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: kind/triage +assignees: '' + +--- + +#### Problem Description +A clear and concise description of what the bug is. + +#### Steps to reproduce the behavior: +1. +2. +3. + +#### System Information +Paste the output of "mitmproxy --version" here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..8e8080db --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: kind/feature +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +#### Describe the solution you'd like +A clear and concise description of what you want to happen. + +#### Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +#### Additional context +Add any other context or screenshots about the feature request here. diff --git a/docs/src/content/howto-install-system-trusted-ca-android.md b/docs/src/content/howto-install-system-trusted-ca-android.md new file mode 100644 index 00000000..2ef67f30 --- /dev/null +++ b/docs/src/content/howto-install-system-trusted-ca-android.md @@ -0,0 +1,86 @@ +--- +title: "Install System CA on Android" +menu: + howto: + weight: 4 +--- + +# Install System CA Certificate on Android Emulator + +[Since Android 7, apps ignore user certificates](https://android-developers.googleblog.com/2016/07/changes-to-trusted-certificate.html), unless they are configured to use them. +As most applications do not explicitly opt in to use user certificates, we need to place our mitmproxy CA certificate in the system certificate store, +in order to avid having to patch each application, which we want to monitor. + +Please note, that apps can decide to ignore the system certificate store and maintain their own CA certificates. In this case you have to patch the application. + +## 1. Prerequisites + + - Emulator from Android SDK with proxy settings pointing to mitmproxy + + - Mitmproxy CA certificate + - Usually located in `~/.mitmproxy/mitmproxy-ca-cert.cer` + - If the folder is empty or does not exist, run `mitmproxy` in order to generate the certificates + +## 2. Rename certificate +Enter your certificate folder +{{< highlight bash >}} +cd ~/.mitmproxy/ +{{< / highlight >}} + + - CA Certificates in Android are stored by the name of their hash, with a '0' as extension + - Now generate the hash of your certificate + +{{< highlight bash >}} +openssl x509 -inform PEM -subject_hash_old -in mitmproxy-ca-cert.cer | head -1 +{{< / highlight >}} +Lets assume, the output is `c8450d0d` + +We can now copy `mitmproxy-ca-cert.cer` to `c8450d0d.0` and our system certificate is ready to use +{{< highlight bash >}} +cp mitmproxy-ca-cert.cer c8450d0d.0 +{{< / highlight >}} + +## 3. Insert certificate into system certificate store + +Note, that Android 9 (API LEVEL 28) was used to test the following steps and that the `emulator` executable is located in the Android SDK + + - Start your android emulator. + - Get a list of your AVDs with `emulator -list-avds` + - Make sure to use the `-writable-system` option. Otherwise it will not be possible to write to `/system` + - Keep in mind, that the **emulator will load a clean system image when starting without `-writable-system` option**. + - This means you always have to start the emulator with `-writable-system` option in order to use your certificate + +{{< highlight bash >}} +emulator -avd <avd_name_here> -writable-system +{{< / highlight >}} + + - Restart adb as root + +{{< highlight bash >}} +adb root +{{< / highlight >}} + + - Get write access to `/system` on the device + - In earlier versions (API LEVEL < 28) of Android you have to use `adb shell "mount -o rw,remount /system"` + +{{< highlight bash >}} +adb shell "mount -o rw,remount /" +{{< / highlight >}} + + - Push your certificate to the system certificate store and set file permissions + +{{< highlight bash >}} +adb push c8450d0d.0 /system/etc/security/cacerts +adb shell "chmod 664 /system/etc/security/cacerts/c8450d0d.0" +{{< / highlight >}} + +## 4. Reboot device and enjoy decrypted TLS traffic + + - Reboot your device. + - You CA certificate should now be system trusted + +{{< highlight bash >}} +adb reboot +{{< / highlight >}} + +**Remember**: You **always** have to start the emulator using the `-writable-system` option in order to use your certificate
\ No newline at end of file diff --git a/mitmproxy/platform/pf.py b/mitmproxy/platform/pf.py index 5e22ec31..74e077a4 100644 --- a/mitmproxy/platform/pf.py +++ b/mitmproxy/platform/pf.py @@ -13,9 +13,15 @@ def lookup(address, port, s): # Those still appear as "127.0.0.1" in the table, so we need to strip the prefix. address = re.sub(r"^::ffff:(?=\d+.\d+.\d+.\d+$)", "", address) s = s.decode() - spec = "%s:%s" % (address, port) + + # ALL tcp 192.168.1.13:57474 -> 23.205.82.58:443 ESTABLISHED:ESTABLISHED + specv4 = "%s:%s" % (address, port) + + # ALL tcp 2a01:e35:8bae:50f0:9d9b:ef0d:2de3:b733[58505] -> 2606:4700:30::681f:4ad0[443] ESTABLISHED:ESTABLISHED + specv6 = "%s[%s]" % (address, port) + for i in s.split("\n"): - if "ESTABLISHED:ESTABLISHED" in i and spec in i: + if "ESTABLISHED:ESTABLISHED" in i and specv4 in i: s = i.split() if len(s) > 4: if sys.platform.startswith("freebsd"): @@ -26,4 +32,11 @@ def lookup(address, port, s): if len(s) == 2: return s[0], int(s[1]) + elif "ESTABLISHED:ESTABLISHED" in i and specv6 in i: + s = i.split() + if len(s) > 4: + s = s[4].split("[") + port = s[1].split("]") + port = port[0] + return s[0], int(port) raise RuntimeError("Could not resolve original destination.") diff --git a/mitmproxy/utils/human.py b/mitmproxy/utils/human.py index 5c02b072..3158a294 100644 --- a/mitmproxy/utils/human.py +++ b/mitmproxy/utils/human.py @@ -48,12 +48,14 @@ def parse_size(s: typing.Optional[str]) -> typing.Optional[int]: raise ValueError("Invalid size specification.") -def pretty_duration(secs): +def pretty_duration(secs: typing.Optional[float]) -> str: formatters = [ (100, "{:.0f}s"), (10, "{:2.1f}s"), (1, "{:1.2f}s"), ] + if secs is None: + return "" for limit, formatter in formatters: if secs >= limit: diff --git a/test/mitmproxy/data/pf01 b/test/mitmproxy/data/pf01 index 3139a289..019a6b76 100644 --- a/test/mitmproxy/data/pf01 +++ b/test/mitmproxy/data/pf01 @@ -1,4 +1,10 @@ No ALTQ support in kernel ALTQ related functions disabled +ALL tcp 192.168.1.111:40001 -> 5.5.5.6:80 FIN_WAIT_2:FIN_WAIT_2 ALL tcp 127.0.0.1:8080 <- 5.5.5.6:80 <- 192.168.1.111:40001 FIN_WAIT_2:FIN_WAIT_2 +ALL tcp 192.168.1.111:40000 -> 5.5.5.5:80 ESTABLISHED:ESTABLISHED ALL tcp 127.0.0.1:8080 <- 5.5.5.5:80 <- 192.168.1.111:40000 ESTABLISHED:ESTABLISHED +ALL tcp 2a01:e35:8bae:50f0:396f:e6c7:f4f1:f3db[40002] -> 2a03:2880:f21f:c5:face:b00c::167[443] ESTABLISHED:ESTABLISHED +ALL tcp ::1[8080] <- 2a03:2880:f21f:c5:face:b00c::167[443] <- 2a01:e35:8bae:50f0:396f:e6c7:f4f1:f3db[40002] ESTABLISHED:ESTABLISHED +ALL tcp 2a01:e35:8bae:50f0:396f:e6c7:f4f1:f3db[40003] -> 2a03:2880:f21f:c5:face:b00c::167[443] FIN_WAIT_2:FIN_WAIT_2 +ALL tcp ::1[6970] <- 2a03:2880:f21f:c5:face:b00c::167[443] <- 2a01:e35:8bae:50f0:396f:e6c7:f4f1:f3db[40003] FIN_WAIT_2:FIN_WAIT_2
\ No newline at end of file diff --git a/test/mitmproxy/platform/test_pf.py b/test/mitmproxy/platform/test_pf.py index 9795a2db..4a7dfe75 100644 --- a/test/mitmproxy/platform/test_pf.py +++ b/test/mitmproxy/platform/test_pf.py @@ -19,3 +19,8 @@ class TestLookup: pf.lookup("192.168.1.112", 40000, d) with pytest.raises(Exception, match="Could not resolve original destination"): pf.lookup("192.168.1.111", 40001, d) + assert pf.lookup("2a01:e35:8bae:50f0:396f:e6c7:f4f1:f3db", 40002, d) == ("2a03:2880:f21f:c5:face:b00c::167", 443) + with pytest.raises(Exception, match="Could not resolve original destination"): + pf.lookup("2a01:e35:8bae:50f0:396f:e6c7:f4f1:f3db", 40003, d) + with pytest.raises(Exception, match="Could not resolve original destination"): + pf.lookup("2a01:e35:face:face:face:face:face:face", 40003, d) diff --git a/test/mitmproxy/utils/test_human.py b/test/mitmproxy/utils/test_human.py index faf35f72..6f8bf732 100644 --- a/test/mitmproxy/utils/test_human.py +++ b/test/mitmproxy/utils/test_human.py @@ -47,6 +47,7 @@ def test_pretty_duration(): assert human.pretty_duration(10000) == "10000s" assert human.pretty_duration(1.123) == "1.12s" assert human.pretty_duration(0.123) == "123ms" + assert human.pretty_duration(None) == "" def test_format_address(): |