File tree Expand file tree Collapse file tree 4 files changed +40
-1
lines changed
android/app/src/main/java/com/masterdns/vpn Expand file tree Collapse file tree 4 files changed +40
-1
lines changed Original file line number Diff line number Diff line change @@ -133,13 +133,27 @@ class MasterDnsVpnService : VpnService() {
133133 }
134134 }
135135
136+ // Detect LOCAL_DNS_ENABLED with a privileged port (<=1024) — requires root on Android.
137+ // Automatically fall back to port 5353 to avoid a bind permission error on non-rooted devices.
138+ val advancedForDns = parseAdvanced(runtimeProfile.advancedJson)
139+ val localDnsEnabled = advancedForDns[" LOCAL_DNS_ENABLED" ].equals(" true" , ignoreCase = true )
140+ val localDnsPort = advancedForDns[" LOCAL_DNS_PORT" ]?.toIntOrNull() ? : 53
141+ val safeDnsPort: Int? = if (! proxyMode && localDnsEnabled && localDnsPort <= 1024 ) {
142+ VpnManager .appendLog(
143+ " WARNING: LOCAL_DNS_PORT=$localDnsPort requires root on Android. " +
144+ " Automatically using port 5353 instead."
145+ )
146+ 5353
147+ } else null
148+
136149 configFile.writeText(
137150 ConfigGenerator .generateConfig(
138151 profile = runtimeProfile,
139152 listenPort = socksPort,
140153 listenIpOverride = listenIpOverride,
141154 protocolOverride = protocolOverride,
142- localDnsEnabledOverride = if (proxyMode) false else null
155+ localDnsEnabledOverride = if (proxyMode) false else null ,
156+ localDnsPortOverride = if (proxyMode) null else safeDnsPort
143157 )
144158 )
145159 if (runtimeProfile.resolvers.isNotBlank()) {
Original file line number Diff line number Diff line change @@ -399,6 +399,31 @@ fun SettingsScreen(
399399 if (! expanded) return @items
400400
401401 Spacer (modifier = Modifier .height(6 .dp))
402+ if (section == " DNS" ) {
403+ val dnsEnabled = fieldsState[" LOCAL_DNS_ENABLED" ].equals(" true" , ignoreCase = true )
404+ val dnsPort = fieldsState[" LOCAL_DNS_PORT" ]?.toIntOrNull() ? : 53
405+ if (dnsEnabled && dnsPort <= 1024 ) {
406+ Card (
407+ colors = CardDefaults .cardColors(
408+ containerColor = MaterialTheme .colorScheme.errorContainer
409+ ),
410+ modifier = Modifier .fillMaxWidth()
411+ ) {
412+ Row (
413+ modifier = Modifier .padding(12 .dp),
414+ verticalAlignment = Alignment .CenterVertically
415+ ) {
416+ Text (
417+ text = " ⚠ Port $dnsPort requires root access on Android. " +
418+ " The app will automatically use port 5353 instead." ,
419+ style = MaterialTheme .typography.bodySmall,
420+ color = MaterialTheme .colorScheme.onErrorContainer
421+ )
422+ }
423+ }
424+ Spacer (modifier = Modifier .height(8 .dp))
425+ }
426+ }
402427 sections[section].orEmpty().forEach { field ->
403428 if ((field.key == " SOCKS5_USER" || field.key == " SOCKS5_PASS" ) && ! socksAuthEnabled) {
404429 return @forEach
You can’t perform that action at this time.
0 commit comments