system_android.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright 2024 The frp Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package system
  15. import (
  16. "context"
  17. "net"
  18. "os/exec"
  19. "strings"
  20. "time"
  21. )
  22. func EnableCompatibilityMode() {
  23. fixTimezone()
  24. fixDNSResolver()
  25. }
  26. // fixTimezone is used to try our best to fix timezone issue on some Android devices.
  27. func fixTimezone() {
  28. out, err := exec.Command("/system/bin/getprop", "persist.sys.timezone").Output()
  29. if err != nil {
  30. return
  31. }
  32. loc, err := time.LoadLocation(strings.TrimSpace(string(out)))
  33. if err != nil {
  34. return
  35. }
  36. time.Local = loc
  37. }
  38. // fixDNSResolver will first attempt to resolve google.com to check if the current DNS is available.
  39. // If it is not available, it will default to using 8.8.8.8 as the DNS server.
  40. // This is a workaround for the issue that golang can't get the default DNS servers on Android.
  41. func fixDNSResolver() {
  42. // First, we attempt to resolve a domain. If resolution is successful, no modifications are necessary.
  43. // In real-world scenarios, users may have already configured /etc/resolv.conf, or compiled directly
  44. // in the Android environment instead of using cross-platform compilation, so this issue does not arise.
  45. if net.DefaultResolver != nil {
  46. timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second)
  47. defer cancel()
  48. _, err := net.DefaultResolver.LookupHost(timeoutCtx, "google.com")
  49. if err == nil {
  50. return
  51. }
  52. }
  53. // If the resolution fails, use 8.8.8.8 as the DNS server.
  54. // Note: If there are other methods to obtain the default DNS servers, the default DNS servers should be used preferentially.
  55. net.DefaultResolver = &net.Resolver{
  56. PreferGo: true,
  57. Dial: func(ctx context.Context, network, addr string) (net.Conn, error) {
  58. if addr == "127.0.0.1:53" || addr == "[::1]:53" {
  59. addr = "8.8.8.8:53"
  60. }
  61. var d net.Dialer
  62. return d.DialContext(ctx, network, addr)
  63. },
  64. }
  65. }