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
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Mail-format patches preserve upstream context and signature whitespace.
buildScript/lib/core/patches/*.patch -whitespace
10 changes: 8 additions & 2 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/setup-go@v5
with:
go-version: ^1.25
go-version: '1.25.11'
cache-dependency-path: libcore/go.sum
- name: Set up Android SDK
if: steps.cache.outputs.cache-hit != 'true'
uses: android-actions/setup-android@v4.0.1
- name: Install Android NDK
if: steps.cache.outputs.cache-hit != 'true'
run: sdkmanager 'ndk;29.0.14206865'
- name: Native Build
if: steps.cache.outputs.cache-hit != 'true'
run: ./run lib core
Expand Down Expand Up @@ -56,7 +63,6 @@ jobs:
BUILD_PLUGIN: none
run: |
echo "sdk.dir=${ANDROID_HOME}" > local.properties
echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
./run init action gradle
./gradlew app:assemblePreviewRelease
Expand Down
11 changes: 8 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/setup-go@v5
with:
go-version: ^1.25
go-version: '1.25.11'
cache-dependency-path: libcore/go.sum
- name: Set up Android SDK
if: steps.cache.outputs.cache-hit != 'true'
uses: android-actions/setup-android@v4.0.1
- name: Install Android NDK
if: steps.cache.outputs.cache-hit != 'true'
run: sdkmanager 'ndk;29.0.14206865'
- name: Native Build
if: steps.cache.outputs.cache-hit != 'true'
run: ./run lib core
Expand Down Expand Up @@ -65,7 +72,6 @@ jobs:
BUILD_PLUGIN: none
run: |
echo "sdk.dir=${ANDROID_HOME}" > local.properties
echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
./run init action gradle
./gradlew app:assembleOssRelease
Expand Down Expand Up @@ -127,7 +133,6 @@ jobs:
- name: Gradle Build
run: |
echo "sdk.dir=${ANDROID_HOME}" > local.properties
echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
./run init action gradle
./gradlew bundlePlayRelease
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ class SagerNet : Application(),
}

if (isMainProcess) {
if (DataStore.trafficSniffing == 2) {
DataStore.trafficSniffing = 1
}
Theme.apply(this)
Theme.applyNightTheme()
runOnDefaultDispatcher {
Expand Down
52 changes: 38 additions & 14 deletions app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import io.nekohasekai.sagernet.fmt.tuic.buildSingBoxOutboundTuicBean
import io.nekohasekai.sagernet.fmt.v2ray.StandardV2RayBean
import io.nekohasekai.sagernet.fmt.v2ray.buildSingBoxOutboundStandardV2RayBean
import io.nekohasekai.sagernet.fmt.wireguard.WireGuardBean
import io.nekohasekai.sagernet.fmt.wireguard.buildSingBoxOutboundWireguardBean
import io.nekohasekai.sagernet.fmt.wireguard.buildSingBoxEndpointWireguardBean
import io.nekohasekai.sagernet.ktx.isIpAddress
import io.nekohasekai.sagernet.ktx.mkPort
import io.nekohasekai.sagernet.utils.PackageCache
Expand Down Expand Up @@ -141,7 +141,6 @@ fun buildConfig(
val enableDnsRouting = DataStore.enableDnsRouting
val useFakeDns = DataStore.enableFakeDns && !forTest
val needSniff = DataStore.trafficSniffing > 0
val needSniffOverride = DataStore.trafficSniffing == 2
val externalIndexMap = ArrayList<IndexEntity>()
val ipv6Mode = if (forTest) IPv6Mode.ENABLE else DataStore.ipv6Mode

Expand Down Expand Up @@ -206,21 +205,20 @@ fun buildConfig(
}
endpoint_independent_nat = true
mtu = DataStore.mtu
domain_strategy = genDomainStrategy(DataStore.resolveDestination)
sniff = needSniff
sniff_override_destination = needSniffOverride
when (ipv6Mode) {
IPv6Mode.DISABLE -> {
inet4_address = listOf(VpnService.PRIVATE_VLAN4_CLIENT + "/28")
address = listOf(VpnService.PRIVATE_VLAN4_CLIENT + "/28")
}

IPv6Mode.ONLY -> {
inet6_address = listOf(VpnService.PRIVATE_VLAN6_CLIENT + "/126")
address = listOf(VpnService.PRIVATE_VLAN6_CLIENT + "/126")
}

else -> {
inet4_address = listOf(VpnService.PRIVATE_VLAN4_CLIENT + "/28")
inet6_address = listOf(VpnService.PRIVATE_VLAN6_CLIENT + "/126")
address = listOf(
VpnService.PRIVATE_VLAN4_CLIENT + "/28",
VpnService.PRIVATE_VLAN6_CLIENT + "/126",
)
}
}
})
Expand All @@ -229,13 +227,11 @@ fun buildConfig(
tag = TAG_MIXED
listen = bind
listen_port = DataStore.mixedPort
domain_strategy = genDomainStrategy(DataStore.resolveDestination)
sniff = needSniff
sniff_override_destination = needSniffOverride
})
}

outbounds = mutableListOf()
endpoints = mutableListOf()

// init routing object
route = RouteOptions().apply {
Expand Down Expand Up @@ -357,7 +353,7 @@ fun buildConfig(
buildSingBoxOutboundShadowsocksBean(bean)

is WireGuardBean ->
buildSingBoxOutboundWireguardBean(bean)
buildSingBoxEndpointWireguardBean(bean)

is SSHBean ->
buildSingBoxOutboundSSHBean(bean)
Expand Down Expand Up @@ -449,7 +445,11 @@ fun buildConfig(
}
}

outbounds.add(currentOutbound)
if (currentOutbound is Endpoint_WireGuardOptions) {
endpoints.add(currentOutbound)
} else {
outbounds.add(currentOutbound)
}
chainOutbounds.add(currentOutbound)
pastOutbound = currentOutbound
pastEntity = proxyEntity
Expand Down Expand Up @@ -738,6 +738,30 @@ fun buildConfig(
}
}

// sing-box 1.13 removed legacy inbound sniff and domain strategy fields.
// Keep these actions ahead of the routing rules they affect.
if (!forTest) {
val inboundTags = buildList {
if (isVPN) add("tun-in")
add(TAG_MIXED)
}
inboundTags.asReversed().forEach { inboundTag ->
if (needSniff) {
route.rules.add(0, Rule_DefaultOptions().apply {
inbound = listOf(inboundTag)
action = "sniff"
})
}
if (DataStore.resolveDestination) {
route.rules.add(0, Rule_DefaultOptions().apply {
inbound = listOf(inboundTag)
action = "resolve"
strategy = genDomainStrategy(true)
})
}
}
}

if (!forTest) _hack_custom_config = DataStore.globalCustomConfig
}.let {
val configMap = it.asMap()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,19 @@ fun genReserved(anyStr: String): String {
}
}

fun buildSingBoxOutboundWireguardBean(bean: WireGuardBean): SingBoxOptions.Outbound_WireGuardOptions {
return SingBoxOptions.Outbound_WireGuardOptions().apply {
fun buildSingBoxEndpointWireguardBean(bean: WireGuardBean): SingBoxOptions.Endpoint_WireGuardOptions {
return SingBoxOptions.Endpoint_WireGuardOptions().apply {
type = "wireguard"
server = bean.serverAddress
server_port = bean.serverPort
local_address = bean.localAddress.listByLineOrComma()
address = bean.localAddress.listByLineOrComma()
private_key = bean.privateKey
peer_public_key = bean.peerPublicKey
pre_shared_key = bean.peerPreSharedKey
mtu = bean.mtu
if (bean.reserved.isNotBlank()) reserved = genReserved(bean.reserved)
peers = listOf(SingBoxOptions.EndpointWireGuardPeer().apply {
address = bean.serverAddress
port = bean.serverPort
public_key = bean.peerPublicKey
pre_shared_key = bean.peerPreSharedKey
allowed_ips = listOf("0.0.0.0/0", "::/0")
if (bean.reserved.isNotBlank()) reserved = genReserved(bean.reserved)
})
}
}
53 changes: 53 additions & 0 deletions app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ public static class MyOptions extends SingBoxOption {

public List<SingBoxOption> outbounds;

public List<SingBoxOption> endpoints;

public RouteOptions route;

public ExperimentalOptions experimental;
Expand Down Expand Up @@ -2803,6 +2805,9 @@ public static class Inbound_TunOptions extends Inbound {

public Integer mtu;

// Generate note: Listable
public List<String> address;

// Generate note: Listable
public List<String> inet4_address;

Expand Down Expand Up @@ -3916,6 +3921,52 @@ public static class Outbound_WireGuardOptions extends Outbound {

}

public static class Endpoint_WireGuardOptions extends Outbound {

// Generate note: nested type DialerOptions
public String detour;

public String bind_interface;

public String protect_path;

public Boolean tcp_fast_open;

public String domain_strategy;

public Boolean system;

public String name;

public List<String> address;

public String private_key;

public List<EndpointWireGuardPeer> peers;

public Integer workers;

public Integer mtu;

}

public static class EndpointWireGuardPeer extends SingBoxOption {

public String address;

public Integer port;

public String public_key;

public String pre_shared_key;

public List<String> allowed_ips;

// Generate note: Base64 String
public String reserved;

}

public static class Outbound_HysteriaOptions extends Outbound {

// Generate note: nested type DialerOptions
Expand Down Expand Up @@ -4454,6 +4505,8 @@ public static class Rule_DefaultOptions extends Rule {

public String action;

public String strategy;

public String outbound;

}
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,11 @@
<string-array name="traffic_sniffing_values">
<item>@string/off</item>
<item>@string/sniff_routing</item>
<item>@string/sniff_override</item>
</string-array>

<string-array name="traffic_sniffing_entry_values" translatable="false">
<item>0</item>
<item>1</item>
</string-array>

</resources>
2 changes: 1 addition & 1 deletion app/src/main/res/xml/global_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
<moe.matsuri.nb4a.ui.SimpleMenuPreference
app:defaultValue="1"
app:entries="@array/traffic_sniffing_values"
app:entryValues="@array/int_array_3"
app:entryValues="@array/traffic_sniffing_entry_values"
app:icon="@drawable/ic_baseline_manage_search_24"
app:key="trafficSniffing"
app:title="@string/traffic_sniffing"
Expand Down
2 changes: 1 addition & 1 deletion buildScript/init/env_ndk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if [ -z "$ANDROID_HOME" ]; then
fi
fi

_NDK="$ANDROID_HOME/ndk/25.0.8775105"
_NDK="$ANDROID_HOME/ndk/29.0.14206865"
[ -f "$_NDK/source.properties" ] || _NDK="$ANDROID_NDK_HOME"
[ -f "$_NDK/source.properties" ] || _NDK="$NDK"
[ -f "$_NDK/source.properties" ] || _NDK="$ANDROID_HOME/ndk-bundle"
Expand Down
7 changes: 6 additions & 1 deletion buildScript/lib/core.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
#!/bin/bash

set -euo pipefail

buildScript/lib/core/init.sh
buildScript/lib/core/build.sh
pushd ../sing-box
go test -count=1 -ldflags='-checklinkname=0' -tags='with_gvisor,with_quic,with_wireguard,with_utls,with_clash_api,badlinkname,tfogo_checklinkname0' ./boxapi ./nekoutils ./common/dialer ./protocol/group ./protocol/vless ./route/rule
popd
buildScript/lib/core/build.sh
3 changes: 2 additions & 1 deletion buildScript/lib/core/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ source "buildScript/init/env.sh"
export CGO_ENABLED=1
export GO386=softfloat

cd libcore
cd libcore || exit 1
go mod tidy
rel=1 ./build.sh || exit 1
19 changes: 16 additions & 3 deletions buildScript/lib/core/get_source.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,36 @@ set -e
source "buildScript/init/env.sh"
ENV_NB4A=1
source "buildScript/lib/core/get_source_env.sh"
ROOT_DIR="$PWD"
pushd ..

####

if [ ! -d "sing-box" ]; then
git clone --no-checkout https://github.com/MatsuriDayo/sing-box.git
git clone --no-checkout "$REPOSITORY_SING_BOX"
fi
pushd sing-box
git checkout "$COMMIT_SING_BOX"
git remote set-url origin "$REPOSITORY_SING_BOX"
git fetch --tags origin
git checkout -B "nb4a-sing-box-${COMMIT_SING_BOX:0:12}" "$COMMIT_SING_BOX"
for patch in "$ROOT_DIR"/buildScript/lib/core/patches/*.patch; do
if git apply --check "$patch"; then
git -c user.name='NekoBoxForAndroid build' -c user.email='build@nekoboxforandroid.invalid' am --3way "$patch"
elif ! git apply --reverse --check "$patch"; then
echo "sing-box patch does not apply: $patch" >&2
exit 1
fi
done
popd

####

if [ ! -d "libneko" ]; then
git clone --no-checkout https://github.com/MatsuriDayo/libneko.git
git clone --no-checkout "$REPOSITORY_LIBNEKO"
fi
pushd libneko
git remote set-url origin "$REPOSITORY_LIBNEKO"
git fetch origin "$COMMIT_LIBNEKO"
git checkout "$COMMIT_LIBNEKO"
popd

Expand Down
6 changes: 5 additions & 1 deletion buildScript/lib/core/get_source_env.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export COMMIT_SING_BOX="aed32ee3066cdbc7d471e3e0415c5134088962df"
export REPOSITORY_SING_BOX="https://github.com/SagerNet/sing-box.git"
export COMMIT_SING_BOX="45ca32dcb966f07f97fc888fe8586e359dbe8405"
export REPOSITORY_LIBNEKO="https://github.com/MatsuriDayo/libneko.git"
export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b"
export REPOSITORY_GOMOBILE="https://github.com/MatsuriDayo/gomobile.git"
export COMMIT_GOMOBILE="17d6af34f6bd6d7e1e428e0c652c8b54a46bda4f"
Loading