mitm.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package clashapi
  2. import (
  3. "context"
  4. "net/http"
  5. "github.com/sagernet/sing-box/adapter"
  6. "github.com/sagernet/sing/common"
  7. "github.com/sagernet/sing/service"
  8. "github.com/go-chi/chi/v5"
  9. "github.com/go-chi/render"
  10. "github.com/gofrs/uuid/v5"
  11. "howett.net/plist"
  12. )
  13. func mitmRouter(ctx context.Context) http.Handler {
  14. r := chi.NewRouter()
  15. r.Get("/mobileconfig", getMobileConfig(ctx))
  16. r.Get("/certificate", getCertificate(ctx))
  17. return r
  18. }
  19. func getMobileConfig(ctx context.Context) http.HandlerFunc {
  20. return func(writer http.ResponseWriter, request *http.Request) {
  21. store := service.FromContext[adapter.CertificateStore](ctx)
  22. if !store.TLSDecryptionEnabled() {
  23. http.NotFound(writer, request)
  24. render.PlainText(writer, request, "TLS decryption not enabled")
  25. return
  26. }
  27. certificate := store.TLSDecryptionCertificate()
  28. writer.Header().Set("Content-Type", "application/x-apple-aspen-config")
  29. uuidGen := common.Must1(uuid.NewV4()).String()
  30. mobileConfig := map[string]interface{}{
  31. "PayloadContent": []interface{}{
  32. map[string]interface{}{
  33. "PayloadCertificateFileName": "Certificates.cer",
  34. "PayloadContent": certificate.Raw,
  35. "PayloadDescription": "Adds a root certificate",
  36. "PayloadDisplayName": certificate.Subject.CommonName,
  37. "PayloadIdentifier": "com.apple.security.root." + uuidGen,
  38. "PayloadType": "com.apple.security.root",
  39. "PayloadUUID": uuidGen,
  40. "PayloadVersion": 1,
  41. },
  42. },
  43. "PayloadDisplayName": certificate.Subject.CommonName,
  44. "PayloadIdentifier": "io.nekohasekai.sfa.ca.profile." + uuidGen,
  45. "PayloadRemovalDisallowed": false,
  46. "PayloadType": "Configuration",
  47. "PayloadUUID": uuidGen,
  48. "PayloadVersion": 1,
  49. }
  50. encoder := plist.NewEncoder(writer)
  51. encoder.Indent("\t")
  52. encoder.Encode(mobileConfig)
  53. }
  54. }
  55. func getCertificate(ctx context.Context) http.HandlerFunc {
  56. return func(writer http.ResponseWriter, request *http.Request) {
  57. store := service.FromContext[adapter.CertificateStore](ctx)
  58. if !store.TLSDecryptionEnabled() {
  59. http.NotFound(writer, request)
  60. render.PlainText(writer, request, "TLS decryption not enabled")
  61. return
  62. }
  63. writer.Header().Set("Content-Type", "application/x-x509-ca-cert")
  64. writer.Header().Set("Content-Disposition", "attachment; filename=Certificate.crt")
  65. writer.Write(store.TLSDecryptionCertificate().Raw)
  66. }
  67. }