mitm.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package clashapi
  2. import (
  3. "archive/zip"
  4. "context"
  5. "crypto/x509"
  6. "encoding/pem"
  7. "io"
  8. "net/http"
  9. "github.com/sagernet/sing-box/adapter"
  10. "github.com/sagernet/sing/common"
  11. "github.com/sagernet/sing/service"
  12. "github.com/go-chi/chi/v5"
  13. "github.com/go-chi/render"
  14. "github.com/gofrs/uuid/v5"
  15. "howett.net/plist"
  16. )
  17. func mitmRouter(ctx context.Context) http.Handler {
  18. r := chi.NewRouter()
  19. r.Get("/mobileconfig", getMobileConfig(ctx))
  20. r.Get("/crt", getCertificate(ctx))
  21. r.Get("/pem", getCertificatePEM(ctx))
  22. r.Get("/magisk", getMagiskModule(ctx))
  23. return r
  24. }
  25. func getMobileConfig(ctx context.Context) http.HandlerFunc {
  26. return func(writer http.ResponseWriter, request *http.Request) {
  27. store := service.FromContext[adapter.CertificateStore](ctx)
  28. if !store.TLSDecryptionEnabled() {
  29. http.NotFound(writer, request)
  30. render.PlainText(writer, request, "TLS decryption not enabled")
  31. return
  32. }
  33. certificate := store.TLSDecryptionCertificate()
  34. writer.Header().Set("Content-Type", "application/x-apple-aspen-config")
  35. uuidGen := common.Must1(uuid.NewV4()).String()
  36. mobileConfig := map[string]interface{}{
  37. "PayloadContent": []interface{}{
  38. map[string]interface{}{
  39. "PayloadCertificateFileName": "Certificates.cer",
  40. "PayloadContent": certificate.Raw,
  41. "PayloadDescription": "Adds a root certificate",
  42. "PayloadDisplayName": certificate.Subject.CommonName,
  43. "PayloadIdentifier": "com.apple.security.root." + uuidGen,
  44. "PayloadType": "com.apple.security.root",
  45. "PayloadUUID": uuidGen,
  46. "PayloadVersion": 1,
  47. },
  48. },
  49. "PayloadDisplayName": certificate.Subject.CommonName,
  50. "PayloadIdentifier": "io.nekohasekai.sfa.ca.profile." + uuidGen,
  51. "PayloadRemovalDisallowed": false,
  52. "PayloadType": "Configuration",
  53. "PayloadUUID": uuidGen,
  54. "PayloadVersion": 1,
  55. }
  56. encoder := plist.NewEncoder(writer)
  57. encoder.Indent("\t")
  58. encoder.Encode(mobileConfig)
  59. }
  60. }
  61. func getCertificate(ctx context.Context) http.HandlerFunc {
  62. return func(writer http.ResponseWriter, request *http.Request) {
  63. store := service.FromContext[adapter.CertificateStore](ctx)
  64. if !store.TLSDecryptionEnabled() {
  65. http.NotFound(writer, request)
  66. render.PlainText(writer, request, "TLS decryption not enabled")
  67. return
  68. }
  69. writer.Header().Set("Content-Type", "application/x-x509-ca-cert")
  70. writer.Header().Set("Content-Disposition", "attachment; filename=Certificate.crt")
  71. writer.Write(store.TLSDecryptionCertificate().Raw)
  72. }
  73. }
  74. func getCertificatePEM(ctx context.Context) http.HandlerFunc {
  75. return func(writer http.ResponseWriter, request *http.Request) {
  76. store := service.FromContext[adapter.CertificateStore](ctx)
  77. if !store.TLSDecryptionEnabled() {
  78. http.NotFound(writer, request)
  79. render.PlainText(writer, request, "TLS decryption not enabled")
  80. return
  81. }
  82. writer.Header().Set("Content-Type", "application/x-pem-file")
  83. writer.Header().Set("Content-Disposition", "attachment; filename=Certificate.pem")
  84. writer.Write(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: store.TLSDecryptionCertificate().Raw}))
  85. }
  86. }
  87. func getMagiskModule(ctx context.Context) http.HandlerFunc {
  88. return func(writer http.ResponseWriter, request *http.Request) {
  89. store := service.FromContext[adapter.CertificateStore](ctx)
  90. if !store.TLSDecryptionEnabled() {
  91. http.NotFound(writer, request)
  92. render.PlainText(writer, request, "TLS decryption not enabled")
  93. return
  94. }
  95. writer.Header().Set("Content-Type", "application/zip")
  96. writer.Header().Set("Content-Disposition", "attachment; filename="+store.TLSDecryptionCertificate().Subject.CommonName+".zip")
  97. createMagiskModule(writer, store.TLSDecryptionCertificate())
  98. }
  99. }
  100. func createMagiskModule(writer io.Writer, certificate *x509.Certificate) error {
  101. zipWriter := zip.NewWriter(writer)
  102. defer zipWriter.Close()
  103. moduleProp, err := zipWriter.Create("module.prop")
  104. if err != nil {
  105. return err
  106. }
  107. _, err = moduleProp.Write([]byte(`
  108. id=sing-box-certificate
  109. name=` + certificate.Subject.CommonName + `
  110. version=v0.0.1
  111. versionCode=1
  112. author=sing-box
  113. description=This module adds ` + certificate.Subject.CommonName + ` to the system trust store.
  114. `))
  115. if err != nil {
  116. return err
  117. }
  118. certificateFile, err := zipWriter.Create("system/etc/security/cacerts/" + certificate.Subject.CommonName + ".pem")
  119. if err != nil {
  120. return err
  121. }
  122. err = pem.Encode(certificateFile, &pem.Block{Type: "CERTIFICATE", Bytes: certificate.Raw})
  123. if err != nil {
  124. return err
  125. }
  126. updateBinary, err := zipWriter.Create("META-INF/com/google/android/update-binary")
  127. if err != nil {
  128. return err
  129. }
  130. _, err = updateBinary.Write([]byte(`
  131. #!/sbin/sh
  132. #################
  133. # Initialization
  134. #################
  135. umask 022
  136. # echo before loading util_functions
  137. ui_print() { echo "$1"; }
  138. require_new_magisk() {
  139. ui_print "*******************************"
  140. ui_print " Please install Magisk v20.4+! "
  141. ui_print "*******************************"
  142. exit 1
  143. }
  144. #########################
  145. # Load util_functions.sh
  146. #########################
  147. OUTFD=$2
  148. ZIPFILE=$3
  149. mount /data 2>/dev/null
  150. [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
  151. . /data/adb/magisk/util_functions.sh
  152. [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk
  153. install_module
  154. exit 0
  155. `))
  156. if err != nil {
  157. return err
  158. }
  159. updaterScript, err := zipWriter.Create("META-INF/com/google/android/updater-script")
  160. if err != nil {
  161. return err
  162. }
  163. _, err = updaterScript.Write([]byte("#MAGISK"))
  164. if err != nil {
  165. return err
  166. }
  167. return nil
  168. }