client_log.go 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package dns
  2. import (
  3. "context"
  4. "strings"
  5. "github.com/sagernet/sing/common/logger"
  6. "github.com/miekg/dns"
  7. )
  8. func logCachedResponse(logger logger.ContextLogger, ctx context.Context, response *dns.Msg, ttl int) {
  9. if logger == nil || len(response.Question) == 0 {
  10. return
  11. }
  12. domain := FqdnToDomain(response.Question[0].Name)
  13. logger.DebugContext(ctx, "cached ", domain, " ", dns.RcodeToString[response.Rcode], " ", ttl)
  14. for _, recordList := range [][]dns.RR{response.Answer, response.Ns, response.Extra} {
  15. for _, record := range recordList {
  16. logger.InfoContext(ctx, "cached ", dns.Type(record.Header().Rrtype).String(), " ", FormatQuestion(record.String()))
  17. }
  18. }
  19. }
  20. func logOptimisticResponse(logger logger.ContextLogger, ctx context.Context, response *dns.Msg) {
  21. if logger == nil || len(response.Question) == 0 {
  22. return
  23. }
  24. domain := FqdnToDomain(response.Question[0].Name)
  25. logger.DebugContext(ctx, "optimistic ", domain, " ", dns.RcodeToString[response.Rcode])
  26. for _, recordList := range [][]dns.RR{response.Answer, response.Ns, response.Extra} {
  27. for _, record := range recordList {
  28. logger.InfoContext(ctx, "optimistic ", dns.Type(record.Header().Rrtype).String(), " ", FormatQuestion(record.String()))
  29. }
  30. }
  31. }
  32. func logExchangedResponse(logger logger.ContextLogger, ctx context.Context, response *dns.Msg, ttl uint32) {
  33. if logger == nil || len(response.Question) == 0 {
  34. return
  35. }
  36. domain := FqdnToDomain(response.Question[0].Name)
  37. logger.DebugContext(ctx, "exchanged ", domain, " ", dns.RcodeToString[response.Rcode], " ", ttl)
  38. for _, recordList := range [][]dns.RR{response.Answer, response.Ns, response.Extra} {
  39. for _, record := range recordList {
  40. logger.InfoContext(ctx, "exchanged ", dns.Type(record.Header().Rrtype).String(), " ", FormatQuestion(record.String()))
  41. }
  42. }
  43. }
  44. func logRefreshedResponse(logger logger.ContextLogger, ctx context.Context, response *dns.Msg, ttl uint32) {
  45. if logger == nil || len(response.Question) == 0 {
  46. return
  47. }
  48. domain := FqdnToDomain(response.Question[0].Name)
  49. logger.DebugContext(ctx, "refreshed ", domain, " ", dns.RcodeToString[response.Rcode], " ", ttl)
  50. for _, recordList := range [][]dns.RR{response.Answer, response.Ns, response.Extra} {
  51. for _, record := range recordList {
  52. logger.InfoContext(ctx, "refreshed ", dns.Type(record.Header().Rrtype).String(), " ", FormatQuestion(record.String()))
  53. }
  54. }
  55. }
  56. func logRejectedResponse(logger logger.ContextLogger, ctx context.Context, response *dns.Msg) {
  57. if logger == nil || len(response.Question) == 0 {
  58. return
  59. }
  60. for _, recordList := range [][]dns.RR{response.Answer, response.Ns, response.Extra} {
  61. for _, record := range recordList {
  62. logger.InfoContext(ctx, "rejected ", dns.Type(record.Header().Rrtype).String(), " ", FormatQuestion(record.String()))
  63. }
  64. }
  65. }
  66. func FqdnToDomain(fqdn string) string {
  67. if dns.IsFqdn(fqdn) {
  68. return fqdn[:len(fqdn)-1]
  69. }
  70. return fqdn
  71. }
  72. func FormatQuestion(string string) string {
  73. for strings.HasPrefix(string, ";") {
  74. string = string[1:]
  75. }
  76. string = strings.ReplaceAll(string, "\t", " ")
  77. string = strings.ReplaceAll(string, "\n", " ")
  78. string = strings.ReplaceAll(string, ";; ", " ")
  79. string = strings.ReplaceAll(string, "; ", " ")
  80. for strings.Contains(string, " ") {
  81. string = strings.ReplaceAll(string, " ", " ")
  82. }
  83. return strings.TrimSpace(string)
  84. }