Запретить телефон Android подключаться к сети Wi-Fi, если мое приложение не одобряет это?

Я хочу разработать приложение, которое может предотвратить подключение к сети Wi-Fi, если я этого не одобряю. Я хочу иметь возможность запрашивать MAC-адрес точки доступа и сравнивать его со списком известных адресов, соответствующих SSID. Цель приложения - защитить пользователей от случайного подключения к вредоносным точкам доступа, например к точкам доступа, которые могут быть созданы с помощью ананасовые устройства.

Из моих исследований мне не ясно, как я смогу достичь этой цели. Такие вопросы, как Как получать уведомления об изменении статуса сети Wi-Fi? объясните, как обнаружить соединение произошло, но для моего варианта использования это уже слишком поздно.

Ни ConnectivityManager, ни WifiManager, похоже, не предлагают методов для добавления слушателей, которые могли бы прервать текущее соединение.

Некоторые мысли, которые у меня были по поводу решения:

  • Установите себя в качестве прокси-сервера и примите решение, пропускать ли данные. Однако это не похоже на вариант, основанный на Применяются ли настройки прокси-сервера Android ко всем приложениям на устройстве? (подсказка: ответ -« Нет »).

  • Замените существующий менеджер Wi-Fi чем-нибудь, созданным мной. Однако мне очень трудно найти в руководствах для разработчиков Android какую-либо информацию о замене системных компонентов. Следовательно, я не уверен, что это возможно на телефонах без рутирования.

  • Хранить сетевые пароли в моем приложении и устанавливать пароли в диспетчере WiFi на бессмысленные значения. Затем перехватите широковещательное сообщение, которое предупреждает о сбое соединения (предположительно, что-то вроде WifiManager.WPS_AUTH_FAILURE), и выборочно решите снова подключиться к этой сети. Может быть возможным (если уродливым) решением, но могу ли я вернуть пароль к бессмысленному значению, пока сеть все еще подключена, чтобы гарантировать, что мы не подключаемся незаметно к другому SSID с тем же именем? Я не уверен. Мне приходит в голову, что устройства типа ананас, вероятно, будут принимать любой пароль, что делает этот подход недействительным.

  • Найдите способ предотвратить автоматическое подключение Android к известным сетям (т. Е. К сетям, которые использовались ранее или для которых хранится пароль). Тогда я мог управлять всеми подключениями / отключениями из моего приложения. Однако я не вижу, как это сделать вручную на моем телефоне, поэтому я сомневаюсь, что это возможно программно.

Может ли кто-нибудь предложить подход, который работал бы на телефоне без рутирования?


person Duncan Jones    schedule 01.11.2014    source источник
comment
Если бы вы могли это сделать, это было бы серьезным недостатком системы безопасности в ОС Android.   -  person Stephan Branczyk    schedule 01.11.2014
comment
@StephanBranczyk Какая именно часть и почему?   -  person Duncan Jones    schedule 01.11.2014
comment
Разрешение одному приложению управлять Wi-Fi других приложений нарушит концепцию песочницы.   -  person Stephan Branczyk    schedule 02.11.2014
comment
@StephanBranczyk Я пытаюсь внести глобальные изменения в Wi-Fi, которые влияют на все приложения. Например, легко написать приложение, которое включает или отключает Wi-Fi, который затрагивает всех. Я также могу подключиться к определенной сети Wi-Fi (например, Как программно подключиться к определенной сети Wi-Fi в Android?). Так почему же я хочу иначе?   -  person Duncan Jones    schedule 05.11.2014
comment
Вы можете попробовать создать службу, которая опрашивает текущий Wi-Fi и, если он подключен, отключиться   -  person Heisenberg    schedule 05.11.2014
comment
@Heisenberg Это не подходит для меня, так как я не хочу, чтобы какие-либо данные передавались в неутвержденные точки доступа.   -  person Duncan Jones    schedule 05.11.2014
comment
Что-то вроде того, что делает это приложение? play.google.com/store/apps/details?id= com.hogdex.WifiRuler   -  person Vrashabh Irde    schedule 05.11.2014
comment
В основном просто любопытство: планируете ли вы распространять свое приложение через Google Play или другими способами?   -  person RenniePet    schedule 06.11.2014
comment
@Slartibartfast Похоже, да. Было бы интересно установить это и посмотреть, заменит ли он менеджер по умолчанию. Я не уверен, что это возможно, поэтому этот вопрос.   -  person Duncan Jones    schedule 06.11.2014
comment
Лучше всего взглянуть на скрытый или внутренний API и посмотреть, сможете ли вы подключиться к сети Wi-Fi. Помимо замены системного менеджера Wi-Fi, это был бы единственный способ прервать фактическое подключение к сети Wi-Fi.   -  person iheanyi    schedule 06.11.2014
comment
@iheanyi Кроме замены системного менеджера Wi-Fi ›Возможно ли это на телефонах без рутирования? Как упоминалось в вопросе, я не нашел никакой информации, объясняющей, что это возможно.   -  person Duncan Jones    schedule 07.11.2014
comment
Вам понадобится либо рутированный телефон, либо телефон с разблокированным загрузчиком, на который была установлена ​​сборка Android, позволяющая заменить системный менеджер Wi-Fi.   -  person iheanyi    schedule 07.11.2014
comment
@Duncan Мне удалось прервать соединение, но не удалось получить BSSID до завершения соединения. Я думаю, что он недоступен или требует дополнительных исследований, если вы хотите просто перебить меня, скажите, я опубликую ответ   -  person Yazan    schedule 09.11.2014
comment
Возможно, вам следует сначала рутировать свои устройства, а затем предоставить разрешение суперпользователя. Но большинству пользователей будет неудобно работать с приложением, для работы которого требуется рутированный телефон.   -  person Hafizh Herdi    schedule 10.11.2014
comment
@HafizhHerdi Если я не могу этого добиться с телефоном без рутирования, я не буду продолжать.   -  person Duncan Jones    schedule 11.11.2014
comment
@RenniePet Извините за поздний ответ, я бы намеревался распространять это через обычные каналы (например, Google Play).   -  person Duncan Jones    schedule 11.11.2014
comment
@Duncan, значит, вас не интересует прерывание соединения? по крайней мере, ответьте на мой комментарий «Нет»!   -  person Yazan    schedule 11.11.2014
comment
@Yazan Извините, я как-то пропустил этот полезный комментарий. Я думаю, если бы вы опубликовали этот ответ, это было бы очень полезным началом (и, безусловно, самым полезным ответом на данный момент). Мне не нужен дамп кода, но мне было бы интересно услышать, как вы это сделали. ScanResult должен предоставлять BSSID, верно? Если так, я могу получить это отдельно.   -  person Duncan Jones    schedule 11.11.2014


Ответы (3)


Вы не можете реализовать очень надежную систему без рутирования устройства. Вот самое близкое, что вы можете получить, я думаю:

  1. Используйте getConfiguredNetworks (), чтобы получить список сетей, настроенных в настоящее время на устройство пользователя
  2. Для каждого WifiConfiguration в списке установите общедоступное поле BSSID на желаемый «безопасный» MAC-адрес.
  3. Вызовите saveConfiguration (), чтобы сохранить изменения.

В качестве альтернативы для шага (2.) вы можете вызвать disableNetwork () для каждой настроенной сети и выборочно включил их на основе BSSID. Обратите внимание, что MAC-адреса все еще можно довольно легко подделать.

person JstnPwll    schedule 06.11.2014
comment
Чтобы сыграть роль адвоката дьявола, ключевая фраза здесь может быть без ведома и согласия пользователя. Если приложение OP не работает с возможностями Wi-Fi только после того, как пользователь поставил галочку в том, что я понимаю, что произойдет, пожалуйста, сделайте это как отказ от ответственности, тогда я думаю, что все должно быть в порядке. - person RenniePet; 06.11.2014
comment
Да ... Вы хотите, чтобы это приложение блокировало доступ к вашим точкам доступа Wi-Fi? - person JstnPwll; 06.11.2014
comment
Я не знаю, для чего предназначено приложение OP. Я немного расскажу о своем приложении для Android, просто как пример того, как приложения могут быть очень нестандартными. Я покупаю старые дешевые телефоны Android на местном аналоге eBay и устанавливаю свое приложение (не в Google Play). Телефон с моим приложением превратился в специальное беспроводное устройство для сигнализации. Ни SIM-карты, ни других приложений. Пользователь может выбрать место, где он (почти всегда женщина в данном контексте) проводит встречу. Если клиент, с которым она встречается, начинает вести себя агрессивно и угрожать, она активирует сигнализацию, и служба безопасности приходит, чтобы убедиться, что все в порядке. - person RenniePet; 06.11.2014
comment
@JustinPowell Возможно, это было неясно из моего исходного текста вопроса, но пользователи установили бы мое приложение специально, потому что оно контролирует их WiFi и не позволяет им подключаться к точкам доступа, маскирующимся под известные сети. Это не нарушит пункт об опасных продуктах, поскольку я не вмешиваюсь в другую инфраструктуру. Это также не будет считаться вмешательством в систему, поскольку пользователь решил установить мое приложение именно для этой цели. - person Duncan Jones; 07.11.2014
comment
@ Дункан А, попался. Так что же больше похоже на систему родительского контроля? Похоже, что это частично уже обрабатывается WifiManager, поскольку пользователям не нужно подключаться к точкам доступа автоматически ... просто по своему усмотрению. Как вы определяете, помечена ли точка доступа как вредоносная? - person JstnPwll; 07.11.2014
comment
@JustinPowell Я еще не уладил все детали. Но я читал отличную статью Троя Ханта об устройствах Pineapple, и он демонстрирует, насколько легко компьютер (и я предполагаю, также телефон) будет подключаться к сохраненным им SSID. Мое приложение, вероятно, ввело бы некоторую проверку MAC-адресов в качестве первой защиты. Возможно, больше защиты, как только я хорошенько об этом подумал. - person Duncan Jones; 07.11.2014
comment
@JustinPowell Я заметил, что вы оставили этот ответ на месте - вы все еще верите, что это правда, основываясь на том, что я сказал до сих пор? - person Duncan Jones; 11.11.2014
comment
Я добавил альтернативный ответ. Наверное, лучшее, что ты можешь сделать. - person JstnPwll; 11.11.2014
comment
@JustinPowell Bingo! Я не понимал, что BSSID можно установить таким образом. Отлично, спасибо, это в значительной степени решает проблему. Я почти наверняка назначу здесь награду, если только кто-то не взорвет меня другим ответом. +1 пока :-) - person Duncan Jones; 11.11.2014

вы можете прослушивать изменение подключения Wi-Fi и действовать в соответствии с этими событиями, чтобы включить отключение Wi-Fi

private ConnectivityManager connectionManager;
boolean previousConnectivityStatus;
private WifiManager wifiManager;

/* Register Connectivity Receiver */
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
context.registerReceiver(networkBroadcastReceiver, intentFilter);

/* Register Wifi State Listener */
IntentFilter wifiStateIntentFilter = new IntentFilter();
wifiStateIntentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
context.registerReceiver(wifiStateReceiver, wifiStateIntentFilter);

connectionManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

private BroadcastReceiver wifiStateReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Utility.traceM("NetworkController.wifiStateReceiver.new BroadcastReceiver() {...}::onReceive");
        int extraWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
        switch (extraWifiState)
            {
            case WifiManager.WIFI_STATE_DISABLED:
                {
                    Utility.trace("Broadcast Wifi State Disabled");
                    if(isWifiStateEventsEnabled)
                    {
                        EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_DISABLED));
                    }
                    break;
                }
            case WifiManager.WIFI_STATE_ENABLED:
                {
                    Utility.trace("Broadcast Wifi State Enabled");
                    if(isWifiStateEventsEnabled)
                    {
                        EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_ENABLED));
                    }
                    break;
                }
            }
    }
};

private BroadcastReceiver networkBroadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Utility.traceM("NetworkController.networkBroadcastReceiver.new BroadcastReceiver() {...}::onReceive");
        boolean connectivityStatus = isInternetConnectivityAvailable();
        if (previousConnectivityStatus != connectivityStatus)
        {
            if (connectivityStatus)
            {
                previousConnectivityStatus = true;
                Utility.trace("Broadcast Internet Available");
                EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_CONNECTED));
            }
            else
            {
                previousConnectivityStatus = false;
                Utility.trace("Broadcast Internet Disconnected");
                EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_DISCONNECTED));
            }
        }
    }
};
person Kirtan    schedule 11.11.2014
comment
Этот код начинает действовать после установления соединения. Я хочу в первую очередь предотвратить соединение. Моя цель состоит в том, чтобы никакие данные не передавались на неподтвержденные точки беспроводного доступа. - person Duncan Jones; 11.11.2014
comment
Это единственный жизнеспособный вариант, который у вас есть, если устройство не рутировано. Я сделал это в своем приложении как для Wi-Fi, так и для мобильных устройств: play.google.com/store/apps/ - person TacB0sS; 11.11.2014

как вы знаете, при подключении к Wi-Fi приложение sifi manager отображает подсказку под именем Wi-Fi, которое подключается,

например, подключение, аутентификация, получение IP ... и т. д.

поэтому я попытался найти, как определить эти этапы подключения к сети Wi-Fi. Я получил ответ, показывающий, как это делается, это было сделано с помощью приемника SUPPLICANT_STATE_CHANGED_ACTION

и я попытался реализовать это, добавив код, чтобы просто отключиться ... и это было успехом, поскольку Wi-Fi никогда не подключался, значок не отображался на панели уведомлений, а журналы продолжают повторять шаги, хотя некоторые, как он говорит, подключен ( в журналах), но на самом устройстве ничего не отображается, так что, возможно, оно подключилось для вроде (10 мс)

так или иначе, ниже приведен код, который я использовал:

public class MyNetworkMonitor extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // EXTRA_BSSID
        // SUPPLICANT_STATE_CHANGED_ACTION
        // EXTRA_NEW_STATE

        // Log.i("YAZAN", intent.getAction() + " " +
        // intent.getStringExtra(WifiManager.EXTRA_BSSID));
        // Log.i("YAZAN", intent.getAction() + " "
        // +intent.getStringExtra(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
        // Log.i("YAZAN", intent.getAction() + " "
        // +intent.getStringExtra(WifiManager.EXTRA_NEW_STATE));

        //Log.i("YAZAN", intent.getAction() + " " + intent.getStringExtra(WifiManager.EXTRA_BSSID));

        String action  = intent.getAction();
        if(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)){

             WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            Log.d("YAZAN", ">>>>SUPPLICANT_STATE_CHANGED_ACTION<<<<<<");
            SupplicantState supl_state=((SupplicantState)intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));

            switch(supl_state){
            case ASSOCIATED:Log.i("YAZAN", "ASSOCIATED");
                break;
            case ASSOCIATING:
                Log.i("YAZAN", "ASSOCIATING");
                 wifi.disconnect();
                 Log.i("YAZAN", "disconnect()");
                break;
            case AUTHENTICATING:Log.i("YAZAN", "Authenticating...");
            wifi.disconnect();
         Log.i("YAZAN", "disconnect()");
                break;
            case COMPLETED:Log.i("YAZAN", "Connected");
                break;
            case DISCONNECTED:Log.i("YAZAN", "Disconnected");
                break;
            case DORMANT:Log.i("YAZAN", "DORMANT");
            wifi.disconnect();
         Log.i("YAZAN", "disconnect()");
                break;
            case FOUR_WAY_HANDSHAKE:Log.i("YAZAN", "FOUR_WAY_HANDSHAKE");
            wifi.disconnect();
         Log.i("YAZAN", "disconnect()");
                break;
            case GROUP_HANDSHAKE:Log.i("YAZAN", "GROUP_HANDSHAKE");
            wifi.disconnect();
         Log.i("YAZAN", "disconnect()");
                break;
            case INACTIVE:Log.i("YAZAN", "INACTIVE");
                break;
            case INTERFACE_DISABLED:Log.i("YAZAN", "INTERFACE_DISABLED");
                break;
            case INVALID:Log.i("YAZAN", "INVALID");
                break;
            case SCANNING:Log.i("YAZAN", "SCANNING");
                break;
            case UNINITIALIZED:Log.i("YAZAN", "UNINITIALIZED");
                break;
            default:Log.i("YAZAN", "Unknown");
                break;

            }
            int supl_error=intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
            if(supl_error==WifiManager.ERROR_AUTHENTICATING){
                Log.i("YAZAN", "ERROR_AUTHENTICATING!");
            }
        }//if

    }// onReceive()

где бы вы ни нашли wifi.disconnect(); вот как я прервал соединение. что здесь остается, это получить сетевое имя или MAC-адрес, чтобы разрешить или запретить завершение процесса.

Разрешения:

<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"/>

добавление широковещательного приемника:

<receiver android:name=".MyNetworkMonitor" >
            <intent-filter>
                <action android:name="android.net.wifi.supplicant.STATE_CHANGE" />
                <action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />

                <action android:name="android.net.wifi.STATE_CHANGE" />

            </intent-filter>
        </receiver>

Благодарность

person Yazan    schedule 12.11.2014
comment
думаю, уже слишком поздно получать награду :( если мой ответ правильный, но здесь это может быть полезно для кого-то другого :) удачи - person Yazan; 12.11.2014
comment
+1 от меня, спасибо за информацию. Я назначил награду Джастину, так как его ответ может помочь избежать хитрости более низкого уровня, как показано в вашем ответе. Но если я в конечном итоге воспользуюсь этим подходом, я обещаю вернуться и устроить вам хорошую награду ;-) - person Duncan Jones; 12.11.2014