【问题标题】:Detect behind VPN in android在 android 中检测 VPN 背后
【发布时间】:2013-04-27 15:02:29
【问题描述】:

如何在不使用意图连接到 VPNService 的情况下以编程方式检测流量是否通过 VPN。有系统调用吗?

【问题讨论】:

    标签: android android-intent vpn


    【解决方案1】:

    这行得通:

    private boolean checkVPN() {
        ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getNetworkInfo(ConnectivityManager.TYPE_VPN).isConnectedOrConnecting();
    }
    

    【讨论】:

    【解决方案2】:

    可以在更高版本的 Android API 21 中检查它,但它似乎不起作用(在 nexus 5 @ 5.0.1、nexus 7 @ 5.0.2 上)。为什么它不起作用?

    用于检查的新 API 的片段(如果连接,所有流量都由 vpn 路由):

    @Inject
    boolean checkVPN(ConnectivityManager connMgr) {
        //don't know why always returns null:
        NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_VPN);
    
        boolean isVpnConn = networkInfo == null ? false : networkInfo.isConnected();
        return isVpnConn;
    }
    

    【讨论】:

      【解决方案3】:

      Android 操作系统知道 VPN 连接何时处于活动状态(因为它会在 VPN 连接期间在状态栏中显示一个图标),但没有公共 API 方法(会出现在 VpnService 上)来检查用于活动连接。

      出现两种解决方案。如果您正在处理您知道网络拓扑的特定情况,请运行“ping”以查看特定 IP 地址是否可用 - 使用 System.exec。 ping 命令存在于具有库存 ROM 的 Android 设备上,我已将其用作解决方案的一部分,以提供更精细的数据连接状态视图(未分配 IP 地址,已分配 IP 地址但无法访问互联网,可以上网)

      更好的解决方案是运行跟踪路由并分析输出。我没有检查是否存在带有库存 ROM 的 Android 设备上的 traceroute,稍后我将使用更完整的信息编辑此答案。

      【讨论】:

      【解决方案4】:

      您可以在 android 中使用以下代码检测 VPN。代码将在新旧版本的 android 中运行。以下代码在 Kotlin 中。

          class MainActivity : AppCompatActivity() {
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_main)
      
              if(checkVPNStatus()) {
                  Log.d("VPN-RAJ", "is VPN Connected YES")
              } else {
                  Log.d("VPN-RAJ", "is VPN Connected NO")
              }
          }
      
      
          private fun checkVPNStatus(): Boolean {
              val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
      
              return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                  val network = connectivityManager.activeNetwork
                  val capabilities = connectivityManager.getNetworkCapabilities(network)
                  Log.d("VPN-RAJ", "in New Android Version")
      
                  capabilities!= null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
      
              } else {
                  Log.d("VPN-RAJ", "in Old Android Version")
      
                  connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_VPN)!!.isConnectedOrConnecting
              }
      
      
          }
      
      
      }
      

      【讨论】:

        【解决方案5】:

        我想对于大多数用例来说,您想检查 主动 使用的网络是否正在使用 VPN,而不是只有 任何 可用的网络正在使用 VPN。

        connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_VPN)
        

        ... 正在返回 一个 可用 VPN 网络的 NetworkInfo。这可能不是活动网络!相反,您可以使用以下 sn-p 来测试活动网络是否正在使用 VPN:

        Network activeNetwork = connectivityManager.getActiveNetwork();
        NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
        boolean vpnInUse = caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-12
          • 2015-10-22
          • 2019-07-08
          • 2021-05-02
          • 1970-01-01
          • 1970-01-01
          • 2011-06-23
          • 2016-03-09
          相关资源
          最近更新 更多