Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ ifeq ($(strip $(APP_VERSION_PUBSPEC)),)
$(error APP_VERSION_PUBSPEC is empty; export APP_VERSION (e.g. "9.0.25+459") or ensure pubspec.yaml contains a `version:` line)
endif
EXTRA_LDFLAGS ?= -X '$(RADIANCE_REPO)/common.Version=$(APP_VERSION_PUBSPEC)'
STEALTH_GO_IMPORT_PATH := github.com/getlantern/lantern/lantern-core
STEALTH_GO_LOG_LEVEL ?= warn
STEALTH_GO_LDFLAGS := $(if $(filter stealth stealth-%,$(BUILD_TYPE)),-X '$(STEALTH_GO_IMPORT_PATH).StealthBuild=true' -X '$(STEALTH_GO_IMPORT_PATH).StealthLogLevel=$(STEALTH_GO_LOG_LEVEL)')
GO_EXTRA_LDFLAGS := $(strip $(EXTRA_LDFLAGS) $(STEALTH_GO_LDFLAGS))
LANTERND_EXTRA_LDFLAGS := $(EXTRA_LDFLAGS)
Comment thread
reflog marked this conversation as resolved.

DARWIN_APP_NAME := $(CAPITALIZED_APP).app
DARWIN_LIB := $(LANTERN_LIB_NAME).dylib
Expand Down Expand Up @@ -68,6 +73,7 @@ LINUX_INSTALLER_RPM := $(INSTALLER_NAME)$(if $(filter-out production,$(BUILD_TYP
LINUX_INSTALLER_ARCH := $(INSTALLER_NAME)$(if $(filter-out production,$(BUILD_TYPE)),-$(BUILD_TYPE))$(LINUX_PACKAGE_ARCH_SUFFIX).pkg.tar.zst
LANTERND := lanternd
LANTERND_SRC := $(RADIANCE_REPO)/cmd/lanternd
LANTERND_SERVICE_LOG_LEVEL ?= $(if $(filter stealth stealth-%,$(BUILD_TYPE)),warn,trace)
LANTERND_LINUX_AMD64 := $(BIN_DIR)/linux-amd64/$(LANTERND)
LANTERND_LINUX_ARM64 := $(BIN_DIR)/linux-arm64/$(LANTERND)
LINUX_BUNDLE_DIR_X64 := build/linux/x64/release/bundle
Expand All @@ -81,10 +87,12 @@ ifeq ($(OS),Windows_NT)
MKDIR_P = $(PS) "New-Item -ItemType Directory -Force -Path '$(1)' | Out-Null"
COPY_FILE = $(PS) "Copy-Item -Force -LiteralPath '$(1)' -Destination '$(2)'"
RM_RF = $(PS) "Remove-Item -Recurse -Force -LiteralPath '$(1)'"
WRITE_TEXT_FILE = $(PS) "Set-Content -LiteralPath '$(2)' -Value '$(1)' -Encoding ASCII"
else
MKDIR_P = mkdir -p -- '$(1)'
COPY_FILE = cp -f -- '$(1)' '$(2)'
RM_RF = rm -rf -- '$(1)'
WRITE_TEXT_FILE = printf '%s\n' '$(1)' > '$(2)'
endif

LANTERND_WINDOWS_AMD64 := $(BIN_DIR)/windows-amd64/$(LANTERND).exe
Expand Down Expand Up @@ -192,7 +200,7 @@ endif
desktop-lib:
$(SETENV) go build -v -trimpath -buildmode=c-shared \
-tags="$(TAGS)" \
-ldflags="-w -s $(EXTRA_LDFLAGS)" \
-ldflags="-w -s $(GO_EXTRA_LDFLAGS)" \
-o $(LIB_NAME) ./$(FFI_DIR)
@echo "Built desktop library: $(LIB_NAME)"

Expand All @@ -216,7 +224,7 @@ $(MACOS_FRAMEWORK_BUILD): $(GO_SOURCES)
-tags=$(TAGS),netgo -trimpath \
-target=macos \
-o $(MACOS_FRAMEWORK_BUILD) \
-ldflags="-w -s -checklinkname=0 $(EXTRA_LDFLAGS)" \
-ldflags="-w -s -checklinkname=0 $(GO_EXTRA_LDFLAGS)" \
$(GOMOBILE_REPOS)
@echo "Built macOS Framework: $(MACOS_FRAMEWORK_BUILD)"
rm -rf $(MACOS_FRAMEWORK_DIR)/$(MACOS_FRAMEWORK)
Expand Down Expand Up @@ -318,15 +326,15 @@ lanternd-linux-amd64: $(GO_SOURCES)
$(call MKDIR_P,$(dir $(LANTERND_LINUX_AMD64)))
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 \
go build -mod=mod -v -trimpath -tags "$(TAGS)" \
-ldflags "-w -s $(EXTRA_LDFLAGS)" \
-ldflags "-w -s $(LANTERND_EXTRA_LDFLAGS)" \
-o $(LANTERND_LINUX_AMD64) $(LANTERND_SRC)
@echo "Built lanternd (linux-amd64): $(LANTERND_LINUX_AMD64)"

lanternd-linux-arm64: $(GO_SOURCES)
$(call MKDIR_P,$(dir $(LANTERND_LINUX_ARM64)))
GOOS=linux GOARCH=arm64 CGO_ENABLED=1 \
go build -mod=mod -v -trimpath -tags "$(TAGS)" \
-ldflags "-w -s $(EXTRA_LDFLAGS)" \
-ldflags "-w -s $(LANTERND_EXTRA_LDFLAGS)" \
-o $(LANTERND_LINUX_ARM64) $(LANTERND_SRC)
@echo "Built lanternd (linux-arm64): $(LANTERND_LINUX_ARM64)"

Expand Down Expand Up @@ -355,6 +363,7 @@ linux-release-ci: linux pubget gen
echo "Using Linux bundle dir: $$BUNDLE_DIR"; \
cp "$(LINUX_LIB_BUILD)" "$$BUNDLE_DIR"; \
cp "$(BIN_DIR)/linux-$(LINUX_TARGET_ARCH)/$(LANTERND)" "$$BUNDLE_DIR"; \
printf '%s\n' "$(LANTERND_SERVICE_LOG_LEVEL)" > "$$BUNDLE_DIR/lanternd-log-level"; \
patchelf --set-rpath '$$ORIGIN/lib' "$$BUNDLE_DIR/lantern" || true; \
VERSION=$(APP_VERSION) GOARCH=$(LINUX_TARGET_ARCH) LINUX_BUNDLE_SRC="$$BUNDLE_DIR/" \
nfpm package -f $(LINUX_PKG_ROOT)/nfpm.yaml -p deb -t $(LINUX_INSTALLER_DEB); \
Expand Down Expand Up @@ -398,15 +407,15 @@ $(LANTERND_WINDOWS_AMD64):
$(call MKDIR_P,$(dir $(LANTERND_WINDOWS_AMD64)))
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -mod=mod -v -trimpath -tags "$(TAGS)" \
-ldflags "$(EXTRA_LDFLAGS)" \
-ldflags "$(LANTERND_EXTRA_LDFLAGS)" \
-o $(LANTERND_WINDOWS_AMD64) $(LANTERND_SRC)
@echo "Built lanternd (windows-amd64): $(LANTERND_WINDOWS_AMD64)"

$(LANTERND_WINDOWS_ARM64):
$(call MKDIR_P,$(dir $(LANTERND_WINDOWS_ARM64)))
GOOS=windows GOARCH=arm64 CGO_ENABLED=0 \
go build -mod=mod -v -trimpath -tags "$(TAGS)" \
-ldflags "$(EXTRA_LDFLAGS)" \
-ldflags "$(LANTERND_EXTRA_LDFLAGS)" \
-o $(LANTERND_WINDOWS_ARM64) $(LANTERND_SRC)
@echo "Built lanternd (windows-arm64): $(LANTERND_WINDOWS_ARM64)"

Expand All @@ -426,6 +435,7 @@ copy-lanternd-debug: $(LANTERND_WINDOWS_AMD64)
prepare-windows-release: lanternd-windows-amd64 lanternd-windows-arm64
$(MAKE) copy-lanternd-release
$(MAKE) copy-lanternd-release-arm64
$(call WRITE_TEXT_FILE,$(LANTERND_SERVICE_LOG_LEVEL),$(WINDOWS_RELEASE_DIR)/lanternd-log-level)

.PHONY: windows-debug
windows-debug: windows
Expand Down Expand Up @@ -491,7 +501,7 @@ build-android: check-android-sdk check-gomobile
-javapkg=lantern.io \
-tags=$(TAGS) -trimpath \
-o=$(ANDROID_LIB_BUILD) \
-ldflags="$(ANDROID_GOMOBILE_LDFLAGS) $(EXTRA_LDFLAGS)" \
-ldflags="$(ANDROID_GOMOBILE_LDFLAGS) $(GO_EXTRA_LDFLAGS)" \
$(GOMOBILE_REPOS)

cp $(ANDROID_LIB_BUILD) $(ANDROID_LIBS_DIR)
Expand Down Expand Up @@ -553,7 +563,7 @@ build-ios:
-tags=$(TAGS),with_low_memory, -trimpath \
-target=ios \
-o $(IOS_FRAMEWORK_BUILD) \
-ldflags="-w -s -checklinkname=0 $(EXTRA_LDFLAGS)" \
-ldflags="-w -s -checklinkname=0 $(GO_EXTRA_LDFLAGS)" \
$(GOMOBILE_REPOS)
@echo "Built iOS Framework: $(IOS_FRAMEWORK_BUILD)"
mv $(IOS_FRAMEWORK_BUILD) $(IOS_FRAMEWORK_DIR)
Expand Down
6 changes: 2 additions & 4 deletions lantern-core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ type EventType = string
const (
EventTypeServerLocation EventType = "server-location"
EventTypeConfig EventType = "config"
DefaultLogLevel = "trace"
)

// LanternCore wraps an IPC client and provides the interface expected by the FFI and mobile layers.
Expand Down Expand Up @@ -180,9 +179,8 @@ func New(opts *utils.Opts, eventEmitter utils.FlutterEventEmitter) (Core, error)
}

core.initOnce.Do(func() {
if opts.LogLevel == "" {
opts.LogLevel = DefaultLogLevel
}
opts.LogLevel = EffectiveLogLevel(opts.LogLevel)
opts.TelemetryConsent = EffectiveTelemetryConsent(opts.TelemetryConsent)
slog.Debug("Initializing LanternCore with opts: ", "opts", opts)
if err := core.initialize(opts, eventEmitter); err != nil {
initError.Store(&err)
Expand Down
2 changes: 1 addition & 1 deletion lantern-core/ffi/ffi.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func setup(_logDir, _dataDir, _locale, _env *C.char, logP, appsP, statusP, priva
Locale: locale,
Env: env,
Deviceid: "",
LogLevel: lanterncore.DefaultLogLevel,
LogLevel: lanterncore.EffectiveLogLevel(""),
TelemetryConsent: consent == 1,
}, &ffiFlutterEventEmitter{})

Expand Down
2 changes: 1 addition & 1 deletion lantern-core/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func setupAppLogging(logDir, level string) {
return
}
if level == "" {
level = DefaultLogLevel
level = EffectiveLogLevel("")
}
logger := rlog.NewLogger(rlog.Config{
LogPath: filepath.Join(logDir, AppLogFileName),
Expand Down
8 changes: 5 additions & 3 deletions lantern-core/mobile/mobile.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func SetQAEnvOverrides(outboundSocks, tz string) error {
// the early values silently override.
func InitLogging(dataDir, logDir, logLevel string) error {
_, err := utils.RunOffCgoStack(func() (struct{}, error) {
return struct{}{}, common.Init(dataDir, logDir, logLevel)
return struct{}{}, common.Init(dataDir, logDir, lanterncore.EffectiveLogLevel(logLevel))
})
return err
}
Expand Down Expand Up @@ -288,13 +288,15 @@ func StartIPCServer(platform utils.PlatformInterface, opts *utils.Opts) error {
if ipcServer != nil {
return struct{}{}, nil
}
logLevel := lanterncore.EffectiveLogLevel(opts.LogLevel)
telemetryConsent := lanterncore.EffectiveTelemetryConsent(opts.TelemetryConsent)
bopts := backend.Options{
DataDir: opts.DataDir,
LogDir: opts.LogDir,
Locale: opts.Locale,
LogLevel: opts.LogLevel,
LogLevel: logLevel,
DeviceID: opts.Deviceid,
TelemetryConsent: opts.TelemetryConsent,
TelemetryConsent: telemetryConsent,
PlatformInterface: platform,
}
be, err := backend.NewLocalBackend(context.Background(), bopts)
Expand Down
90 changes: 90 additions & 0 deletions lantern-core/stealth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package lanterncore

import (
"os"
"strings"
)

const (
// DefaultLogLevel preserves the existing non-stealth production behavior.
DefaultLogLevel = "trace"

safeStealthLogLevel = "warn"
)

var (
// StealthBuild is set by release tooling with:
//
// -X github.com/getlantern/lantern/lantern-core.StealthBuild=true
//
// Runtime env fallbacks are kept for local validation until the full
// native stealth profile plumbing lands in getlantern/lantern#8763.
StealthBuild = "false"
Comment thread
reflog marked this conversation as resolved.

// StealthLogLevel is the Go/Radiance fallback log level for stealth builds.
// Empty and trace-level defaults are deliberately replaced by
// EffectiveLogLevel.
StealthLogLevel = safeStealthLogLevel
)

func IsStealthBuild() bool {
if buildBool(StealthBuild) {
return true
}
return buildBool(firstNonEmpty(
os.Getenv("LANTERN_STEALTH_BUILD"),
os.Getenv("STEALTH_BUILD"),
))
Comment thread
reflog marked this conversation as resolved.
}

func EffectiveLogLevel(configured string) string {
configured = strings.ToLower(strings.TrimSpace(configured))
if !IsStealthBuild() {
if configured == "" {
return DefaultLogLevel
}
return configured
}

if configured == "" || configured == "trace" {
return effectiveStealthLogLevel()
}
return configured
}

func EffectiveTelemetryConsent(configured bool) bool {
// The current platform callers pass a stored consent bool, not a tri-state
// value. Preserve explicit user opt-out until callers can distinguish
// "unset" from "disabled" before applying any build default.
return configured
}

func effectiveStealthLogLevel() string {
level := strings.ToLower(strings.TrimSpace(firstNonEmpty(
os.Getenv("LANTERN_STEALTH_LOG_LEVEL"),
os.Getenv("STEALTH_LOG_LEVEL"),
StealthLogLevel,
)))
if level == "" || level == "trace" {
return safeStealthLogLevel
}
return level
}

func firstNonEmpty(values ...string) string {
for _, value := range values {
if strings.TrimSpace(value) != "" {
return value
}
}
return ""
}

func buildBool(value string) bool {
switch strings.ToLower(strings.TrimSpace(value)) {
case "1", "true", "yes", "y", "on":
return true
default:
return false
}
}
107 changes: 107 additions & 0 deletions lantern-core/stealth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package lanterncore

import "testing"

func clearStealthEnv(t *testing.T) {
t.Setenv("LANTERN_STEALTH_BUILD", "")
t.Setenv("STEALTH_BUILD", "")
t.Setenv("LANTERN_STEALTH_LOG_LEVEL", "")
t.Setenv("STEALTH_LOG_LEVEL", "")
t.Setenv("LANTERN_STEALTH_TELEMETRY_DEFAULT_ENABLED", "")
t.Setenv("STEALTH_TELEMETRY_DEFAULT_ENABLED", "")
}

func TestEffectiveLogLevelNonStealthPreservesDefaultTrace(t *testing.T) {
clearStealthEnv(t)
origStealthBuild := StealthBuild
StealthBuild = "false"
t.Cleanup(func() { StealthBuild = origStealthBuild })

if got := EffectiveLogLevel(""); got != DefaultLogLevel {
t.Fatalf("EffectiveLogLevel(\"\") = %q, want %q", got, DefaultLogLevel)
}
if got := EffectiveLogLevel("debug"); got != "debug" {
t.Fatalf("EffectiveLogLevel(\"debug\") = %q, want debug", got)
}
}

func TestEffectiveLogLevelStealthReplacesTraceDefault(t *testing.T) {
clearStealthEnv(t)
t.Setenv("STEALTH_BUILD", "true")
t.Setenv("STEALTH_LOG_LEVEL", "")
Comment thread
reflog marked this conversation as resolved.
origStealthBuild := StealthBuild
origStealthLogLevel := StealthLogLevel
StealthBuild = "false"
StealthLogLevel = "warn"
t.Cleanup(func() {
StealthBuild = origStealthBuild
StealthLogLevel = origStealthLogLevel
})

for _, configured := range []string{"", "trace", "TRACE"} {
if got := EffectiveLogLevel(configured); got != safeStealthLogLevel {
t.Fatalf("EffectiveLogLevel(%q) = %q, want %q", configured, got, safeStealthLogLevel)
}
}
if got := EffectiveLogLevel("error"); got != "error" {
t.Fatalf("EffectiveLogLevel(\"error\") = %q, want error", got)
}
}

func TestEffectiveLogLevelStealthRejectsTraceFallback(t *testing.T) {
clearStealthEnv(t)
t.Setenv("STEALTH_BUILD", "true")
t.Setenv("STEALTH_LOG_LEVEL", "trace")
Comment thread
reflog marked this conversation as resolved.
origStealthBuild := StealthBuild
origStealthLogLevel := StealthLogLevel
StealthBuild = "false"
StealthLogLevel = "trace"
t.Cleanup(func() {
StealthBuild = origStealthBuild
StealthLogLevel = origStealthLogLevel
})

if got := EffectiveLogLevel(""); got != safeStealthLogLevel {
t.Fatalf("EffectiveLogLevel(\"\") = %q, want %q", got, safeStealthLogLevel)
}
}

func TestIsStealthBuildLinkedValueCannotBeDisabledByEnv(t *testing.T) {
clearStealthEnv(t)
t.Setenv("LANTERN_STEALTH_BUILD", "false")
t.Setenv("STEALTH_BUILD", "false")
origStealthBuild := StealthBuild
StealthBuild = "true"
t.Cleanup(func() { StealthBuild = origStealthBuild })

if !IsStealthBuild() {
t.Fatal("linked stealth build should remain enabled despite false env fallbacks")
}
}

func TestEffectiveTelemetryConsent(t *testing.T) {
clearStealthEnv(t)
origStealthBuild := StealthBuild
t.Cleanup(func() {
StealthBuild = origStealthBuild
})

StealthBuild = "false"
Comment thread
reflog marked this conversation as resolved.
if got := EffectiveTelemetryConsent(false); got {
t.Fatal("non-stealth false consent should remain false")
}
if got := EffectiveTelemetryConsent(true); !got {
t.Fatal("explicit true consent should remain true")
}

StealthBuild = "true"
if got := EffectiveTelemetryConsent(false); got {
t.Fatal("stealth false consent should preserve explicit opt-out")
}

t.Setenv("LANTERN_STEALTH_TELEMETRY_DEFAULT_ENABLED", "true")
t.Setenv("STEALTH_TELEMETRY_DEFAULT_ENABLED", "true")
if got := EffectiveTelemetryConsent(false); got {
t.Fatal("stealth telemetry env defaults must not override explicit opt-out")
}
}
3 changes: 2 additions & 1 deletion linux/packaging/arch/postinstall.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/sh
set -e

/usr/lib/lantern/lanternd install --log-level=trace >/dev/null 2>&1 || true
LOG_LEVEL="$(cat /usr/lib/lantern/lanternd-log-level 2>/dev/null || printf '%s' trace)"
/usr/lib/lantern/lanternd install --log-level="$LOG_LEVEL" >/dev/null 2>&1 || true
Loading
Loading