• 26-07-2023, 12:41:34
    #1
    Merhaba flutter de vpn başlatılabiliyor ama vpn bağlantısı kesilemiyor. Lütfen yardımcı olabilecek biri var mı
  • 26-07-2023, 15:40:51
    #2
    Flutterda daha yeniyim isterseniz beraber bakabiliriz.
  • 26-07-2023, 16:21:09
    #3
    kullandığın paketi ve vpn bağlantısı yaptığın kodların bir kısmını paylaşırmısın
    çünkü direkt olarak VPN bağlantısını kesmek mümkün değildir, kullanıcı tarafından yapılması gereklidir.
  • 26-07-2023, 22:11:47
    #4
    OmerAti adlı üyeden alıntı: mesajı görüntüle
    kullandığın paketi ve vpn bağlantısı yaptığın kodların bir kısmını paylaşırmısın
    çünkü direkt olarak VPN bağlantısını kesmek mümkün değildir, kullanıcı tarafından yapılması gereklidir.
    Şöyle tunnelservice.kt dosyam

    package com.sail_tunnel.sail
    
    import android.app.Service
    import android.content.Intent
    import android.net.*
    import android.os.Build
    import android.os.ParcelFileDescriptor
    import com.sail_tunnel.sail.net.DefaultNetworkListener
    import com.sail_tunnel.sail.net.DnsResolverCompat
    import com.sail_tunnel.sail.services.VpnState
    import com.sail_tunnel.sail.services.LocalDnsWorker
    import com.sail_tunnel.sail.services.TunnelInstance
    import com.sail_tunnel.sail.utils.readableMessage
    import kotlinx.coroutines.*
    import java.io.File
    import java.io.IOException
    
    class TunnelService : VpnService() {
    companion object {
    private const val CORE_NAME = "leaf"
    private const val VPN_MTU = 1500
    private const val PRIVATE_VLAN4_CLIENT = "194.36.88.50"
    private const val PRIVATE_VLAN4_ROUTER = "1.1.1.1"
    }
    
    inner class NullConnectionException : NullPointerException() {
    override fun getLocalizedMessage() =
    "Failed to start VPN service. You might need to reboot your device."
    }
    
    private val data = VpnState.Data()
    
    private fun startRunner() {
    if (Build.VERSION.SDK_INT >= 26) startForegroundService(Intent(this, javaClass))
    else startService(Intent(this, javaClass))
    }
    
    private var pfd: ParcelFileDescriptor? = null
    private var active = false
    private var metered = false
    
    @Volatile
    private var underlyingNetwork: Network? = null
    set(value) {
    field = value
    if (active) setUnderlyingNetworks(underlyingNetworks)
    }
    private val underlyingNetworks
    get() =
    // clearing underlyingNetworks makes Android 9 consider the network to be metered
    if (Build.VERSION.SDK_INT == 28 && metered) null else underlyingNetwork?.let {
    arrayOf(
    it
    )
    }
    
    override fun onRevoke() = stopRunner()
    
    private fun killProcesses(scope: CoroutineScope) {
    data.proxy?.run {
    shutdown(scope)
    data.proxy = null
    }
    data.localDns?.shutdown(scope)
    data.localDns = null
    
    active = false
    scope.launch { DefaultNetworkListener.stop(this) }
    pfd?.close()
    pfd = null
    }
    
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    val data = data
    if (data.state != VpnState.State.Stopped) return Service.START_NOT_STICKY
    
    try {
    data.proxy = TunnelInstance()
    } catch (e: IllegalArgumentException) {
    stopRunner(false, e.message)
    return Service.START_NOT_STICKY
    }
    
    data.changeState(VpnState.State.Connecting)
    data.connectingJob = GlobalScope.launch(Dispatchers.Main) {
    try {
    preInit()
    
    startVpn()
    
    data.changeState(VpnState.State.Connected)
    } catch (_: CancellationException) {
    // if the job was cancelled, it is canceller's responsibility to call stopRunner
    } catch (exc: Throwable) {
    stopRunner(false, exc.readableMessage)
    } finally {
    data.connectingJob = null
    }
    }
    
    return START_NOT_STICKY
    }
    
    private suspend fun preInit() = DefaultNetworkListener.start(this) { underlyingNetwork = it }
    private suspend fun rawResolver(query: ByteArray) =
    // no need to listen for network here as this is only used for forwarding local DNS queries.
    // retries should be attempted by client.
    DnsResolverCompat.resolveRaw(underlyingNetwork ?: throw IOException("no network"), query)
    
    private suspend fun startVpn() {
    val builder = Builder()
    .setConfigureIntent(Core.configureIntent(this))
    .setSession(CORE_NAME)
    .setMtu(VPN_MTU)
    .addAddress(PRIVATE_VLAN4_CLIENT, 24)
    .addDnsServer(PRIVATE_VLAN4_ROUTER)
    .addRoute("0.0.0.0", 0)
    
    active = true // possible race condition here?
    builder.setUnderlyingNetworks(underlyingNetworks)
    if (Build.VERSION.SDK_INT >= 29) builder.setMetered(metered)
    
    this.pfd = builder.establish() ?: throw NullConnectionException()
    
    val context = Core.deviceStorage
    val configRoot = context.noBackupFilesDir
    
    data.localDns = LocalDnsWorker(this::rawResolver).apply { start() }
    
    val configFile = File(configRoot, VpnState.CONFIG_FILE)
    val configContent = configFile
    .readText()
    .replace("{{leafLogFile}}", File(configRoot, VpnState.LEAF_LOG_FILE).absolutePath)
    .replace("{{tunFd}}", this.pfd?.fd?.toLong().toString())
    
    configFile.writeText(configContent)
    
    data.proxy!!.start(
    this,
    File(Core.deviceStorage.noBackupFilesDir, "stat_main"),
    configFile,
    )
    }
    
    private fun stopRunner(restart: Boolean = false, msg: String? = null) {
    if (data.state == VpnState.State.Stopping) return
    // channge the state
    data.changeState(VpnState.State.Stopping)
    GlobalScope.launch(Dispatchers.Main.immediate) {
    data.connectingJob?.cancelAndJoin() // ensure stop connecting first
    // we use a coroutineScope here to allow clean-up in parallel
    coroutineScope {
    killProcesses(GlobalScope)
    }
    
    // change the state
    data.changeState(VpnState.State.Stopped, msg)
    
    // stop the service if nothing has bound to it
    if (restart) startRunner() else {
    stopSelf()
    }
    }
    }
    }


    bu da app model kodum. Buton işlevi

    import 'package:flutter/material.dart';
    import 'package:fluttertoast/fluttertoast.dart';
    import 'package:sail/adapters/leaf_ffi/config.dart';
    import 'package:sail/channels/vpn_manager.dart';
    import 'package:sail/constant/app_colors.dart';
    import 'package:sail/constant/app_strings.dart';
    import 'package:sail/models/base_model.dart';
    import 'package:sail/models/server_model.dart';
    import 'package:sail/models/user_model.dart';
    import 'package:sail/utils/common_util.dart';
    
    class AppModel extends BaseModel {
    VpnManager vpnManager = VpnManager();
    VpnStatus vpnStatus = VpnStatus.disconnected;
    bool isOn = false;
    DateTime? connectedDate;
    PageController pageController = PageController(initialPage: 0);
    String appTitle = AppStrings.appName;
    Config config = Config();
    ThemeData themeData = ThemeData(
    primarySwatch: AppColors.themeColor,
    visualDensity: VisualDensity.adaptivePlatformDensity,
    );
    
    AppModel() {
    General general = General(
    loglevel: 'info',
    logoutput: '{{leafLogFile}}',
    dnsServer: ['223.5.5.5', '114.114.114.114'],
    tunFd: '{{tunFd}}',
    routingDomainResolve: true);
    
    List<Rule> rules = [];
    // rules.add(Rule(typeField: 'EXTERNAL', target: 'Direct', filter: 'site:cn'));
        rules.add(Rule(typeField: 'FINAL', target: 'Direct'));
    
    config.general = general;
    config.rules = rules;
    }
    
    final Map _tabMap = {
    0: AppStrings.appName,
    1: 'Paketler',
    2: 'Sunucular',
    3: 'Hesap Ayarları',
    };
    
    void jumpToPage(int page) {
    pageController.jumpToPage(page);
    appTitle = _tabMap[page];
    
    notifyListeners();
    }
    
    void getStatus() async {
    vpnStatus = await vpnManager.getStatus();
    
    if (vpnStatus == VpnStatus.connected) {
    isOn = true;
    
    
    notifyListeners();
    } else if (vpnStatus == VpnStatus.disconnected) {
    isOn = false;
    notifyListeners();
    }
    }
    
    
    
    void togglePowerButton() async {
    if (vpnStatus == VpnStatus.connecting) {
    Fluttertoast.showToast(
    msg: "Bağlanıyor, lütfen bekleyin...",
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.CENTER,
    timeInSecForIosWeb: 2,
    textColor: Colors.white,
    fontSize: 14.0);
    return;
    }
    
    if (vpnStatus == VpnStatus.disconnecting) {
    Fluttertoast.showToast(
    msg: "Bağlantı kesiliyor, lütfen bekleyin...",
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.CENTER,
    timeInSecForIosWeb: 2,
    textColor: Colors.white,
    fontSize: 14.0);
    return;
    }
    
    if (vpnStatus == VpnStatus.connected) {
    vpnStatus = VpnStatus.disconnecting;
    }
    
    if (vpnStatus == VpnStatus.disconnected) {
    vpnStatus = VpnStatus.connecting;
    }
    
    await vpnManager.toggle();
    
    notifyListeners();
    }
    
    void getTunnelLog() async {
    var log = await vpnManager.getTunnelLog();
    
    print("log: $log");
    }
    
    void getTunnelConfiguration() async {
    var conf = await vpnManager.getTunnelConfiguration();
    
    print("config: $conf");
    }
    
    void setConfigProxies(UserModel userModel, ServerModel serverModel) async {
    List<Proxy> proxies = [];
    List<ProxyGroup> proxyGroups = [];
    List<String> actors = [];
    
    for (var server in serverModel.serverEntityList) {
    Proxy proxy = Proxy(
    tag: server.name,
    protocol: server.type,
    address: server.host,
    port: server.port,
    encryptMethod: server.cipher,
    password: userModel.userEntity!.uuid);
    proxies.add(proxy);
    actors.add(server.name);
    }
    
    if (actors.isNotEmpty) {
    proxyGroups.add(ProxyGroup(
    tag: "UrlTest",
    protocol: 'url-test',
    actors: actors,
    checkInterval: 600));
    
    config.rules?.last.target = "UrlTest";
    }
    
    config.proxies = proxies;
    config.proxyGroups = proxyGroups;
    
    print("-----------------config-----------------");
    print(config);
    print("-----------------config-----------------");
    
    vpnManager.setTunnelConfiguration(config.toString());
    }
    
    void setConfigRule(String tag) async {
    // var proxy = config.proxies?.where((proxies) => proxies.tag == tag);
        //
        // if (proxy == null || proxy.isEmpty) {
        //   return;
        // }
        //
        // config.rules?.last.target = tag;
        //
        // print("-----------------config-----------------");
        // print(config);
        // print("-----------------config-----------------");
        //
        // vpnManager.setTunnelConfiguration(config.toString());
      }
    }
  • 26-07-2023, 22:55:35
    #5
    TunnelService.kt:
    • İşlev stopRunner(), VPN hizmetini durdurmaktan soruml
    • Uygulama, VPN bağlantısının kesilmesini istediğinde çağrılır.
    • Ayrıca, VPN bağlantısı başlatılamadığında da çağrılır.
    AppModel.dart:
    • İşlev togglePowerButton(), VPN bağlantısını değiştirmekten sorumludur.
    • Mevcut VPN durumunu kontrol ediyor ve bağlanıp bağlanmamaya karar veriyor
    class TunnelService : VpnService() {
        override fun onRevoke() {
            stopRunner(true) // Revoke the VPN connection and restart the service if needed
        }
    
        private fun stopRunner(restart: Boolean = false, msg: String? = null) {
            if (data.state == VpnState.State.Stopping) return
                data.changeState(VpnState.State.Stopping)
            GlobalScope.launch(Dispatchers.Main.immediate) {
                data.connectingJob?.cancelAndJoin() // Ensure stop connecting first
                coroutineScope {
                    killProcesses(this) 
                }
                data.changeState(VpnState.State.Stopped, msg)
                if (restart) startRunner() else {
                    stopSelf()
                }
            }
        }
    
        private fun killProcesses(scope: CoroutineScope) {
            data.proxy?.run {
                shutdown(scope)
                data.proxy = null
            }
            data.localDns?.shutdown(scope)
            data.localDns = null
    
            active = false
            scope.launch { DefaultNetworkListener.stop(this) }
            pfd?.close()
            pfd = null
        }
    }
    class AppModel extends BaseModel {
    
        void togglePowerButton() async {
            if (vpnStatus == VpnStatus.connecting) {
                Fluttertoast.showToast(
                    msg: "Bağlanıyor, lütfen bekleyin...",
                    toastLength: Toast.LENGTH_SHORT,
                    gravity: ToastGravity.CENTER,
                    timeInSecForIosWeb: 2,
                    textColor: Colors.white,
                    fontSize: 14.0,
                );
                return;
            }
    
            if (vpnStatus == VpnStatus.disconnecting) {
                Fluttertoast.showToast(
                    msg: "Bağlantı kesiliyor, lütfen bekleyin...",
                    toastLength: Toast.LENGTH_SHORT,
                    gravity: ToastGravity.CENTER,
                    timeInSecForIosWeb: 2,
                    textColor: Colors.white,
                    fontSize: 14.0,
                );
                return;
            }
    
            if (vpnStatus == VpnStatus.connected) {
                vpnStatus = VpnStatus.disconnecting;
            } else if (vpnStatus == VpnStatus.disconnected) {
                vpnStatus = VpnStatus.connecting;
            }
    
            await vpnManager.toggle();
    
            notifyListeners();
        }
    
    }
    kodunuzda ufak bir güncelleme yaptim gerektigi gibi degiştirin istediginiz sonucu alabilirsiniz
  • 26-07-2023, 23:13:07
    #6
    OmerAti adlı üyeden alıntı: mesajı görüntüle
    TunnelService.kt:
    • İşlev stopRunner(), VPN hizmetini durdurmaktan soruml
    • Uygulama, VPN bağlantısının kesilmesini istediğinde çağrılır.
    • Ayrıca, VPN bağlantısı başlatılamadığında da çağrılır.
    AppModel.dart:
    • İşlev togglePowerButton(), VPN bağlantısını değiştirmekten sorumludur.
    • Mevcut VPN durumunu kontrol ediyor ve bağlanıp bağlanmamaya karar veriyor
    class TunnelService : VpnService() {
        override fun onRevoke() {
            stopRunner(true) // Revoke the VPN connection and restart the service if needed
        }
    
        private fun stopRunner(restart: Boolean = false, msg: String? = null) {
            if (data.state == VpnState.State.Stopping) return
                data.changeState(VpnState.State.Stopping)
            GlobalScope.launch(Dispatchers.Main.immediate) {
                data.connectingJob?.cancelAndJoin() // Ensure stop connecting first
                coroutineScope {
                    killProcesses(this)
                }
                data.changeState(VpnState.State.Stopped, msg)
                if (restart) startRunner() else {
                    stopSelf()
                }
            }
        }
    
        private fun killProcesses(scope: CoroutineScope) {
            data.proxy?.run {
                shutdown(scope)
                data.proxy = null
            }
            data.localDns?.shutdown(scope)
            data.localDns = null
    
            active = false
            scope.launch { DefaultNetworkListener.stop(this) }
            pfd?.close()
            pfd = null
        }
    }
    class AppModel extends BaseModel {
    
        void togglePowerButton() async {
            if (vpnStatus == VpnStatus.connecting) {
                Fluttertoast.showToast(
                    msg: "Bağlanıyor, lütfen bekleyin...",
                    toastLength: Toast.LENGTH_SHORT,
                    gravity: ToastGravity.CENTER,
                    timeInSecForIosWeb: 2,
                    textColor: Colors.white,
                    fontSize: 14.0,
                );
                return;
            }
    
            if (vpnStatus == VpnStatus.disconnecting) {
                Fluttertoast.showToast(
                    msg: "Bağlantı kesiliyor, lütfen bekleyin...",
                    toastLength: Toast.LENGTH_SHORT,
                    gravity: ToastGravity.CENTER,
                    timeInSecForIosWeb: 2,
                    textColor: Colors.white,
                    fontSize: 14.0,
                );
                return;
            }
    
            if (vpnStatus == VpnStatus.connected) {
                vpnStatus = VpnStatus.disconnecting;
            } else if (vpnStatus == VpnStatus.disconnected) {
                vpnStatus = VpnStatus.connecting;
            }
    
            await vpnManager.toggle();
    
            notifyListeners();
        }
    
    }
    kodunuzda ufak bir güncelleme yaptim gerektigi gibi degiştirin istediginiz sonucu alabilirsiniz
    Öncelikle yardımınız için çok teşekkür ederim. kodları ilgili yere tam uyarlayamadım sanırım. size gönderdiğim kodlar üzerinden revize edip yollamanız mümkün mü acaba.