Pārlūkot izejas kodu

set CompatibilityMode for android (#4091)

fatedier 10 mēneši atpakaļ
vecāks
revīzija
f16ef00975

+ 1 - 1
Makefile.cross-compiles

@@ -2,7 +2,7 @@ export PATH := $(PATH):`go env GOPATH`/bin
 export GO111MODULE=on
 LDFLAGS := -s -w
 
-os-archs=darwin:amd64 darwin:arm64 freebsd:amd64 linux:amd64 linux:arm linux:arm64 windows:amd64 windows:arm64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat linux:riscv64
+os-archs=darwin:amd64 darwin:arm64 freebsd:amd64 linux:amd64 linux:arm linux:arm64 windows:amd64 windows:arm64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat linux:riscv64 android:arm64
 
 all: build
 

+ 1 - 0
Release.md

@@ -17,6 +17,7 @@
   This will create 8 proxies such as `tcp-6000, tcp-6001, ... tcp-6007`.
 
 * Health check supports custom request headers.
+* Enable compatibility mode for the Android system to solve the issues of incorrect log time caused by time zone problems and default DNS resolution failures.
 
 ### Fixes
 

+ 2 - 0
cmd/frpc/main.go

@@ -17,8 +17,10 @@ package main
 import (
 	_ "github.com/fatedier/frp/assets/frpc"
 	"github.com/fatedier/frp/cmd/frpc/sub"
+	"github.com/fatedier/frp/pkg/util/system"
 )
 
 func main() {
+	system.EnableCompatibilityMode()
 	sub.Execute()
 }

+ 2 - 3
cmd/frps/main.go

@@ -15,13 +15,12 @@
 package main
 
 import (
-	"github.com/fatedier/golib/crypto"
-
 	_ "github.com/fatedier/frp/assets/frps"
 	_ "github.com/fatedier/frp/pkg/metrics"
+	"github.com/fatedier/frp/pkg/util/system"
 )
 
 func main() {
-	crypto.DefaultSalt = "frp"
+	system.EnableCompatibilityMode()
 	Execute()
 }

+ 2 - 2
pkg/util/net/dns.go

@@ -26,8 +26,8 @@ func SetDefaultDNSAddress(dnsAddress string) {
 	// Change default dns server
 	net.DefaultResolver = &net.Resolver{
 		PreferGo: true,
-		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
-			return net.Dial("udp", dnsAddress)
+		Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
+			return net.Dial(network, dnsAddress)
 		},
 	}
 }

+ 22 - 0
pkg/util/system/system.go

@@ -0,0 +1,22 @@
+// Copyright 2024 The frp Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build !android
+
+package system
+
+// EnableCompatibilityMode enables compatibility mode for different system.
+// For example, on Android, the inability to obtain the correct time zone will result in incorrect log time output.
+func EnableCompatibilityMode() {
+}

+ 66 - 0
pkg/util/system/system_android.go

@@ -0,0 +1,66 @@
+// Copyright 2024 The frp Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package system
+
+import (
+	"context"
+	"net"
+	"os/exec"
+	"strings"
+	"time"
+)
+
+func EnableCompatibilityMode() {
+	fixTimezone()
+	fixDNSResolver()
+}
+
+// fixTimezone is used to try our best to fix timezone issue on some Android devices.
+func fixTimezone() {
+	out, err := exec.Command("/system/bin/getprop", "persist.sys.timezone").Output()
+	if err != nil {
+		return
+	}
+	loc, err := time.LoadLocation(strings.TrimSpace(string(out)))
+	if err != nil {
+		return
+	}
+	time.Local = loc
+}
+
+// fixDNSResolver will first attempt to resolve google.com to check if the current DNS is available.
+// If it is not available, it will default to using 8.8.8.8 as the DNS server.
+// This is a workaround for the issue that golang can't get the default DNS servers on Android.
+func fixDNSResolver() {
+	// First, we attempt to resolve a domain. If resolution is successful, no modifications are necessary.
+	// In real-world scenarios, users may have already configured /etc/resolv.conf, or compiled directly
+	// in the Android environment instead of using cross-platform compilation, so this issue does not arise.
+	if net.DefaultResolver != nil {
+		timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second)
+		defer cancel()
+		_, err := net.DefaultResolver.LookupHost(timeoutCtx, "google.com")
+		if err == nil {
+			return
+		}
+	}
+	// If the resolution fails, use 8.8.8.8 as the DNS server.
+	// Note: If there are other methods to obtain the default DNS servers, the default DNS servers should be used preferentially.
+	net.DefaultResolver = &net.Resolver{
+		PreferGo: true,
+		Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
+			return net.Dial(network, "8.8.8.8:53")
+		},
+	}
+}

+ 2 - 0
server/service.go

@@ -26,6 +26,7 @@ import (
 	"strconv"
 	"time"
 
+	"github.com/fatedier/golib/crypto"
 	"github.com/fatedier/golib/net/mux"
 	fmux "github.com/hashicorp/yamux"
 	quic "github.com/quic-go/quic-go"
@@ -61,6 +62,7 @@ const (
 )
 
 func init() {
+	crypto.DefaultSalt = "frp"
 	// Disable quic-go's receive buffer warning.
 	os.Setenv("QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING", "true")
 	// Disable quic-go's ECN support by default. It may cause issues on certain operating systems.