Wi-Fi او ډیری نور لنډیزونه. د انډرایډ اپلیکیشن کې د وائی فای نوډونو په اړه معلومات څنګه ترلاسه کول پرته له پړسوب څخه

یوه ورځ ما اړتیا درلوده چې د Android غوښتنلیکونو څخه د Wi-Fi شبکې سکین کړم او د لاسرسي نقطو په اړه مفصل معلومات ترلاسه کړم.

دلته موږ له څو ستونزو سره مخ شو: off.Android اسناد ډیری تشریح شوي ټولګي له مینځه وړل شوي (د API کچه> 26)، کوم چې په دې کې منعکس شوي ندي؛ په اسنادو کې د ځینو شیانو توضیحات لږ تر لږه دي (د بیلګې په توګه، د ټولګي د وړتیا ساحه د سکین پایلې د لیکلو په وخت کې، تقریبا هیڅ شی ندی بیان شوی، که څه هم دا ډیری مهم معلومات لري). دریم مشکل ممکن پدې حقیقت کې وي چې کله تاسو لومړی وائی فای ته نږدې شئ ، د تیوري لوستلو او د لوکل هوسټ له لارې روټر تنظیم کولو پرته ، تاسو باید د یو شمیر لنډیزونو سره معامله وکړئ چې په انفرادي ډول د پوهیدو وړ ښکاري. مګر دا ممکن روښانه نه وي چې څنګه دوی سره تړاو او جوړښت وکړي (قضاوت موضوعي دی او په تیرو تجربو پورې اړه لري).

دا مقاله د NDK ، هیکونو پرته د Android کوډ څخه د Wi-Fi چاپیریال په اړه هراړخیز ډیټا ترلاسه کولو څرنګوالي په اړه بحث کوي ، مګر یوازې د Android API کارولو او پوهیدل چې څنګه یې تشریح کړئ.

راځئ چې ځنډ ونه کړو او د کوډ لیکل پیل کړو.

1. یوه پروژه جوړه کړئ

دا نوټ د هغو کسانو لپاره دی چې له یو ځل څخه ډیر د Android پروژه رامینځته کړې ، نو موږ د دې توکي توضیحات له پامه غورځوو. لاندې کوډ به په کوټلین کې وړاندې شي، minSdkVersion=23.

2. د لاسرسي اجازه

د غوښتنلیک څخه د Wi-Fi سره کار کولو لپاره ، تاسو اړتیا لرئ د کارونکي څخه څو اجازې ترلاسه کړئ. د..سره په سمون اسناد، د 8.0 څخه وروسته د OS نسخو سره په وسیلو کې د شبکې سکین کولو لپاره ، د شبکې چاپیریال حالت لیدو ته د لاسرسي سربیره ، تاسو د وسیلې د Wi-Fi ماډل حالت بدلولو لپاره لاسرسي ته اړتیا لرئ ، یا همغږي ته لاسرسی (نږدې یا دقیق). د 9.0 نسخه سره پیل کول، تاسو باید د دواړو لپاره کاروونکي ته اشاره وکړئ، او په واضح ډول د کارونکي څخه غوښتنه وکړئ چې د موقعیت خدمتونه فعال کړي. مه هیروئ چې په زړورتیا سره کارونکي ته تشریح کړئ چې دا د ګوګل سپیڅلی دی، او زموږ د هغه د جاسوسۍ هیله نه ده :)

نو، په AndroidManifest.xml کې به موږ اضافه کړو:

    <uses-permission android_name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android_name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android_name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android_name="android.permission.ACCESS_FINE_LOCATION"/>

او په کوډ کې چې د اوسني فعالیت لپاره لینک لري:

import android.app.Activity
import android.content.Context
import android.location.LocationManager
import androidx.core.app.ActivityCompat

....

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
            makeEnableLocationServices(activity.applicationContext)
        } else {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
        }

    /* включает экран включения службы по определению местоположения */
    fun makeEnableLocationServices(context: Context) {
        // TODO: перед вызовом этой функции надо рассказать пользователю, зачем Вам доступ к местоположению
        val lm: LocationManager =
            context.applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager

        val gpsEnabled: Boolean = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        val networkEnabled: Boolean = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!gpsEnabled && !networkEnabled) {
            context.startActivity(Intent(ACTION_LOCATION_SOURCE_SETTINGS));
        }
    }

3. د براډکاسټ ریسیور رامینځته کړئ او د Wi-Fi شبکې چاپیریال سکین کولو په اړه د ډیټا تازه پیښو کې ګډون وکړئ

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager

val wifiScanReceiver = object : BroadcastReceiver() {

  override fun onReceive(context: Context, intent: Intent) {
    val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)
    if (success) {
      scanSuccess()
    } 
  }
}

val intentFilter = IntentFilter()
/* подписываемся на сообщения о получении новых результатов сканирования */
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
context.registerReceiver(wifiScanReceiver, intentFilter)

val success = wifiManager.startScan()
if (!success) {
  /* что-то не получилось при запуске сканирования, проверьте выданые разрешения */
}

....

private fun scanSuccess() {
 /* вот они, результаты сканирования */
  val results: List<ScanResult> = wifiManager.scanResults
}

په اسنادو کې د WiFiManager.startScan میتود د API نسخه 28 راهیسې د محروم شوي په توګه نښه شوی، مګر بند دی. الرښوونه د کارولو وړاندیز کوي.

په مجموع کې، موږ د شیانو لیست ترلاسه کړ د سکین پایلې.

4. د ScanResult وګورئ او شرایط درک کړئ

راځئ چې د دې ټولګي ځینې برخې وګورو او تشریح کړو چې دوی څه معنی لري:

SSID - د خدماتو سیټ پیژندونکی د شبکې نوم دی

BSSID - د لومړني خدمت سیټ پیژندونکی - د شبکې اډاپټر MAC پته (وائی فای نقطه)

کچه د - ترلاسه شوي سیګنال ځواک شاخص [dBm (روسي dBm) - ډیسیبل، د حوالې ځواک 1 mW.] - د ترلاسه شوي سیګنال ځواک شاخص. له 0 څخه تر -100 پورې ارزښت اخلي، هرڅومره چې له 0 څخه نور ، د Wi-Fi پوائنټ څخه ستاسو آلې ته د لارې په اوږدو کې د سیګنال ځواک له لاسه ورکړ. نور جزییات موندل کیدی شي، د بیلګې په توګه، په ويکيپېډيا. دلته به زه تاسو ته ووایم چې د Android ټولګي کارول د وائی فای مدیر تاسو کولی شئ د سیګنال کچه په پیمانه کې له غوره څخه تر ډارونکي پورې په هغه مرحله کې چې تاسو یې غوره کوئ:

        val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val numberOfLevels = 5
        val level = WifiManager.calculateSignalLevel(level, numberOfLevels)

د فریکونسي - د وای فای نقطې عملیاتي فریکونسۍ [Hz]. د فریکونسۍ سربیره، تاسو ممکن د تش په نامه چینل سره علاقه ولرئ. هر ټکی خپل عملیاتي پاکتیا لري. د لیکلو په وخت کې، د Wi-Fi پوائنټونو ترټولو مشهور حد 2.4 GHz دی. مګر ، د ډیر دقیق کیدو لپاره ، نقطه ستاسو تلیفون ته معلومات په یوه شمیره فریکونسۍ کې لیږدوي چې نوم ته نږدې وي. د چینلونو شمیر او اړونده فریکونسۍ معیاري. دا د دې لپاره ترسره کیږي چې نږدې ټکي په مختلف فریکونسیو کې کار کوي، په دې توګه د یو بل سره مداخله نه کوي او په متقابل ډول د لیږد سرعت او کیفیت کموي. په دې حالت کې، ټکي په یوه فریکونسۍ کې کار نه کوي، مګر د فریکونسۍ په لړۍ کې (پیرامیټ د چینل پراخوالی)، د چینل عرض ویل کیږي. دا هغه ټکي دي چې په څنګ کې فعالیت کوي (او نه یوازې نږدې ، بلکې حتی 3 پخپله) چینلونه یو بل سره مداخله کوي. تاسو ممکن دا ساده کوډ ګټور ومومئ، کوم چې تاسو ته اجازه درکوي د 2.4 او 5 Ghz فریکونسۍ سره د پوائنټونو لپاره د فریکونسۍ ارزښت څخه د چینل شمیره محاسبه کړئ:


    /* по частоте определяем номер канала */
    val channel: Int
        get() {
            return if (frequency in 2412..2484) {
                (frequency - 2412) / 5 + 1
            } else if (frequency in 5170..5825) {
                (frequency - 5170) / 5 + 34
            } else {
                -1
            }
        }

وړتیاوې - د تحلیل لپاره خورا په زړه پوري ساحه، هغه کار چې ډیر وخت ته اړتیا لري. دلته د نقطې "وړتیاوې" په کرښه کې لیکل شوي. په دې حالت کې، تاسو اړتیا نلرئ په اسنادو کې د تار تشریح توضیحات وګورئ. دلته ځینې مثالونه دي چې په دې کرښه کې څه کیدی شي:

[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][WPS][ESS]
[WPA2-PSK-CCMP][ESS]
[WPA2-PSK-CCMP+TKIP][ESS]
[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS]
[ESS][WPS]

5. د مخففاتو او تجزیه کولو وړتیاو پوهیدل

د یادولو وړ ده چې د android.net.wifi.* کڅوړې ټولګي د لینوکس یوټیلیټ لخوا د هود لاندې کارول کیږي wpa_supplicant او د وړتیاو په ساحه کې د محصول پایله د سکین کولو پرمهال د فلګ ساحې یوه کاپي ده.

موږ به په دوامداره توګه عمل وکړو. راځئ چې لومړی د یوې بڼې محصول په پام کې ونیسو په کوم کې چې د قوس دننه عناصر د "-" نښه سره جلا شوي دي:

[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]

لومړی معنی تشريح کوي. د تصدیق طریقه. دا د عملونو کوم ترتیب دی چې وسیله او د لاسرسي نقطه باید د لاسرسي نقطې لپاره ترسره کړي ترڅو ځان ته اجازه ورکړي چې وکارول شي او د تادیې کوډ کولو څرنګوالی. د دې پوسټ لیکلو په وخت کې، ترټولو عام اختیارونه WPA او WPA2 دي، په کوم کې چې هر یو وصل شوی وسیله مستقیم یا د تش په نامه له لارې. د RADIUS سرور (WPA-Enterprice) په کوډ شوي چینل کې پټنوم چمتو کوي. ډیری احتمال، ستاسو په کور کې د لاسرسي نقطه د دې سکیم مطابق اړیکه چمتو کوي. د دویمې نسخې او لومړۍ نسخې ترمنځ توپیر دا دی چې دا یو پیاوړی سیفر لري: AES د ناامنه TKIP په مقابل کې. WPA3، کوم چې ډیر پیچلی او پرمختللی دی، په تدریجي ډول معرفي کیږي. په تیوریکي توګه، ممکن د تصدۍ حل CCKM (د سیسکو مرکزي شوي کلیدي مدیریت) سره یو اختیار وي، مګر زه هیڅکله ورته نه یم رسیدلی.

د لاسرسي نقطه ممکن د MAC پتې لخوا تصدیق کولو لپاره تنظیم شوې وي. یا، که چیرې د لاسرسي نقطه د زاړه شوي WEP الګوریتم په کارولو سره ډاټا چمتو کړي، نو په حقیقت کې هیڅ تصدیق شتون نلري (دلته پټ کیلي د کوډ کولو کیلي ده). موږ دا ډول اختیارونه د نورو په توګه طبقه بندي کوو.
دلته یو میتود هم شتون لري چې په عامه وائی فای کې د پټ کیپټیو پورټل کشف سره مشهور دی - د براوزر له لارې د تصدیق غوښتنه. د لاسرسي دا ډول ټکي سکینر ته د خلاص په توګه ښکاري (کوم چې دوی د فزیکي اړیکې له نظره دي). له همدې امله، موږ دوی د خلاص په توګه طبقه بندي کوو.

دوهم ارزښت په توګه اشاره کیدی شي کلیدي مدیریت الګوریتم. دا د تصدیق کولو میتود یو پیرامیټر دی چې پورته تشریح شوي. د دې په اړه خبرې کوي چې څنګه د کوډ کولو کیلي تبادله کیږي. راځئ چې ممکنه اختیارونه په پام کې ونیسو. EAP - په ذکر شوي WPA-Enterprice کې کارول کیږي، د داخل شوي تصدیق ډاټا تصدیق کولو لپاره ډیټابیس کاروي. SAE - په پرمختللي WPA3 کې کارول کیږي، د وحشي ځواک لپاره ډیر مقاومت لري. PSK - ترټولو عام انتخاب، د پټنوم داخلول او په کوډ شوي بڼه کې لیږدول شامل دي. IEEE8021X - د نړیوال معیار سره سم (له هغه څخه توپیر چې د WPA کورنۍ لخوا ملاتړ کیږي). OWE (موقعیت لرونکی بې سیم کوډ کول) د IEEE 802.11 معیاري غزول دي د پوائنټونو لپاره چې موږ د خلاص په توګه طبقه بندي کړی. OWE د کوډ کولو له لارې په ناامنه شبکه کې د لیږد شوي معلوماتو امنیت تضمینوي. یو اختیار هم امکان لري کله چې د لاسرسي کیلي شتون نلري ، راځئ چې دې اختیار ته NONE ووایو.

دریم پیرامیټر ورته ویل کیږي. د کوډ کولو سکیمونه - څنګه په ریښتیا سره د لیږد شوي معلوماتو خوندي کولو لپاره سایفر کارول کیږي. راځئ چې اختیارونه لیست کړو. WEP - د RC4 سټریم سیفر کاروي، پټ کیلي د کوډ کولو کیلي ده، کوم چې د عصري کریپټوګرافۍ نړۍ کې د منلو وړ نه ګڼل کیږي. TKIP - په WPA کې کارول کیږي، CKIP - په WPA2 کې. TKIP + CKIP - د شاته مطابقت لپاره د WPA او WPA2 وړ ټکو کې مشخص کیدی شي.

د دریو عناصرو پر ځای، تاسو کولی شئ یوازینی WEP نښه ومومئ:

[WEP]

لکه څنګه چې موږ پورته بحث وکړ، دا کافی دی چې د کیلي کارولو لپاره الګوریتم مشخص نه کړي، کوم چې شتون نلري، او د کوډ کولو طریقه، کوم چې په ډیفالټ ورته وي.

اوس دې بریکٹ ته پام وکړئ:

[ESS]

د دې د وای فای عملیاتي حالت او یا د وای فای شبکې ټوپولوژي. تاسو ممکن د BSS (اساسي خدماتو سیټ) حالت سره مخ شئ - کله چې د لاسرسي یوه نقطه شتون ولري چې له لارې وصل شوي وسایل اړیکه نیسي. په محلي شبکو کې موندل کیدی شي. د یوې قاعدې په توګه، د مختلف محلي شبکو څخه د وسایلو سره نښلولو لپاره د لاسرسي نقطو ته اړتیا ده، نو دا د پراخ شوي خدماتو سیټونو برخه ده - ESS. د IBSSs (د خپلواک بنسټیز خدماتو سیټونو) ډول په ګوته کوي چې وسیله د Peer-to-Peer شبکې برخه ده.

تاسو ممکن د WPS بیرغ هم وګورئ:

[WPS]

WPS (Wi-Fi محافظت شوی ترتیب) د Wi-Fi شبکې نیمه اتوماتیک پیل کولو پروتوکول دی. د پیل کولو لپاره، کاروونکي یا د 8-حروف پاسورډ داخلوي یا په روټر کې تڼۍ فشاروي. که ستاسو د لاسرسي نقطه لومړی ډول وي او دا چیک باکس ستاسو د لاسرسي نقطې نوم سره نږدې ښکاري ، تاسو ته په کلکه سپارښتنه کیږي چې اډمین پینل ته لاړشئ او د WPS لاسرسی غیر فعال کړئ. حقیقت دا دی چې ډیری وختونه د 8 عددي PIN د MAC ادرس لخوا موندل کیدی شي ، یا دا په نږدې وخت کې ترتیب کیدی شي ، کوم چې یو څوک په خیانت سره ګټه پورته کولی شي.

6. یو ماډل او د پارس کولو فعالیت رامینځته کړئ

د هغه څه پر بنسټ چې موږ پورته وموندل، موږ به تشریح کړو چې د ډیټا ټولګیو په کارولو سره څه پیښ شوي:

/* схема аутентификации */
enum class AuthMethod {
    WPA3,
    WPA2,
    WPA, // Wi-Fi Protected Access
    OTHER, // включает в себя Shared Key Authentication и др. использующие mac-address-based и WEP
    CCKM, // Cisco
    OPEN // Open Authentication. Может быть со скрытым Captive Portal Detection - запрос аутентификации через браузер
}

/* алгоритм ввода ключей */
enum class KeyManagementAlgorithm {
    IEEE8021X, // по стандарту
    EAP, // Extensible Authentication Protocol, расширяемый протокол аутентификации
    PSK, // Pre-Shared Key — каждый узел вводит пароль для доступа к сети
    WEP, // в WEP пароль является ключом шифрования (No auth key)
    SAE, // Simultaneous Authentication of Equals - может быть в WPA3
    OWE, // Opportunistic Wireless Encryption - в роутерах новых поколений, публичных сетях типа OPEN
    NONE // может быть без шифрования в OPEN, OTHER
}

/* метод шифрования */
enum class CipherMethod {
    WEP, // Wired Equivalent Privacy, Аналог шифрования трафика в проводных сетях
    TKIP, // Temporal Key Integrity Protocol
    CCMP, // Counter Mode with Cipher Block Chaining Message Authentication Code Protocol,
    // протокол блочного шифрования с кодом аутентичности сообщения и режимом сцепления блоков и счетчика
    // на основе AES
    NONE // может быть без шифрования в OPEN, OTHER
}

/* набор методов шифрования и протоколов, по которым может работать точка */
data class Capability(
    var authScheme: AuthMethod? = null,
    var keyManagementAlgorithm: KeyManagementAlgorithm? = null,
    var cipherMethod: CipherMethod? = null
)

/* Режим работы WiFi (или топология сетей WiFi) */
enum class TopologyMode {
    IBSS, // Эпизодическая сеть (Ad-Hoc или IBSS – Independent Basic Service Set).
    BSS, // Основная зона обслуживания Basic Service Set (BSS) или Infrastructure Mode.
    ESS // Расширенная зона обслуживания ESS – Extended Service Set.
}

اوس راځئ چې یو فنکشن ولیکئ چې د وړتیا ساحه به تجزیه کړي:


private fun parseCapabilities(capabilitiesString: String): List < Capability > {
    val capabilities: List < Capability > = capabilitiesString
        .splitByBrackets()
        .filter {
            !it.isTopology() && !it.isWps()
        }
        .flatMap {
            parseCapability(it)
        }
    return
        if (!capabilities.isEmpty()) {
            capabilities
        } else {
            listOf(Capability(AuthMethod.OPEN, KeyManagementAlgorithm.NONE, CipherMethod.NONE))
        }
}

private fun parseCapability(part: String): List < Capability > {
    if (part.contains("WEP")) {
        return listOf(Capability(
            AuthMethod.OTHER,
            KeyManagementAlgorithm.WEP,
            CipherMethod.WEP
        ))
    }

    val authScheme = when {
        part.contains("WPA3") - > AuthMethod.WPA3
        part.contains("WPA2") - > AuthMethod.WPA2
        part.contains("WPA") - > AuthMethod.WPA
        else - > null
    }

    val keyManagementAlgorithm = when {
        part.contains("OWE") - > KeyManagementAlgorithm.OWE
        part.contains("SAE") - > KeyManagementAlgorithm.SAE
        part.contains("IEEE802.1X") - > KeyManagementAlgorithm.IEEE8021X
        part.contains("EAP") - > KeyManagementAlgorithm.EAP
        part.contains("PSK") - > KeyManagementAlgorithm.PSK
        else - > null
    }

    val capabilities = ArrayList < Capability > ()
    if (part.contains("TKIP") || part.contains("CCMP")) {
        if (part.contains("TKIP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.TKIP
            ))
        }
        if (part.contains("CCMP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.CCMP
            ))
        }
    } else if (authScheme != null || keyManagementAlgorithm != null) {
        capabilities.add(Capability(
            authScheme ? : AuthMethod.OPEN,
            keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
            CipherMethod.NONE
        ))
    }

    return capabilities
}

private fun parseTopologyMode(capabilitiesString: String): TopologyMode ? {
    return capabilitiesString
        .splitByBrackets()
        .mapNotNull {
            when {
                it.contains("ESS") - > TopologyMode.ESS
                it.contains("BSS") - > TopologyMode.BSS
                it.contains("IBSS") - > TopologyMode.IBSS
                else - > null
            }
        }
        .firstOrNull()
}

private fun parseWPSAvailable(capabilitiesString: String): Boolean {
    return capabilitiesString
        .splitByBrackets()
        .any {
            it.isWps()
        }
}

private fun String.splitByBrackets(): List < String > {
    val m = Pattern.compile("[(.*?)]").matcher(this)
    val parts = ArrayList < String > ()
    while (m.find()) {
        parts.add(m.group().replace("[", "").replace("]", ""))
    }
    return parts
}

private fun String.isTopology(): Boolean {
    return TopologyMode.values().any {
        this == it.name
    }
}

private fun String.isWps(): Boolean {
    return this == "WPS"
}

8. پایله وګورئ

زه به شبکه سکین کړم او تاسو ته به وښیم چې ما څه وموندل. د Log.d له لارې د ساده محصول پایلې ښودل شوي:

Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true

د غوښتنلیک کوډ څخه د شبکې سره د وصل کولو مسله غیر څیړل شوې. زه به یوازې ووایم چې د ګرځنده وسیلې له OS څخه خوندي شوي پاسورډونو لوستلو لپاره ، تاسو د روټ حقونو او د فایل سیسټم له لارې د wpa_supplicant.conf لوستلو لپاره لیوالتیا ته اړتیا لرئ. که چیرې د غوښتنلیک منطق له بهر څخه د پټنوم داخلولو ته اړتیا ولري ، اړیکه د ټولګي له لارې رامینځته کیدی شي android.net.wifi.WifiManager.

سپوږمکۍ ایګور پونوماریف د ارزښتناکو اضافو لپاره.

که تاسو فکر کوئ چې یو څه اضافه کولو یا سمولو ته اړتیا لري، په نظرونو کې ولیکئ :)

سرچینه: www.habr.com

Add a comment