Main Content

WLAN ルーター偽装を検出するためのシミュレーション データを使用した深層ニューラル ネットワークの設計

この例では、シミュレーション データを使用して無線周波数 (RF) 指紋の畳み込みニューラル ネットワーク (CNN) を設計する方法を示します。シミュレートした既知および未知のルーターからの無線ローカル エリア ネットワーク (WLAN) ビーコン フレームを使用して、CNN に RF 指紋を学習させます。その後、受信信号のメディア アクセス制御 (MAC) アドレスを CNN で検出された RF 指紋と比較することで WLAN ルーター偽装者を検出します。

設計したニューラル ネットワークを実際の Wi-Fi® ルーターから取得した信号でテストする方法の詳細については、WLAN ルーター偽装を検出するための取得データを使用した深層ニューラル ネットワークのテストの例を参照してください。

RF 指紋を使用したルーター偽装の検出

ルーター偽装は、WLAN ネットワークに対する攻撃の一種で、悪意のある行為者が正規のルーターを偽装してネットワーク ユーザーが接続するように仕向ける攻撃です。このような攻撃の検出に対しては、MAC アドレス、IP アドレス、SSID などの単純なデジタル識別子に基づくセキュリティ識別ソリューションは効果がありません。これらの識別子はなりすましが簡単だからです。したがって、より安全なソリューションでは、単純なデジタル識別子に加え、無線リンクの RF シグネチャなど、他の情報を使用します。

無線の送信機と受信機のペアごとに、受信機側でチャネル障害と RF 損失を組み合わせた一意の RF シグネチャが作成されます。"RF 指紋" は、これらのシグネチャを使用して共有スペクトルから送信元無線機を判別するプロセスです。[1] の著者は、生のベースバンド同相/直交 (IQ) サンプルを使用して送信元無線機を識別する深層学習 (DL) ネットワークを設計しています。このネットワークでは、RF 損失が優勢となる場合や演算時にチャネル プロファイルが一定のままである場合に送信元無線機を識別できます。ほとんどの WLAN ネットワークでは、ルーターは固定であり、受信機の位置も固定であれば静的なチャネル プロファイルが作成されます。このようなシナリオでは、深層学習ネットワークで受信信号の RF 指紋と MAC アドレスのペアを既知のルーターと比較することでルーター偽装者を識別できます。

この例では、WLAN Toolbox™ を使用して複数の固定ルーターと 1 つの固定オブザーバーで構成される WLAN システムをシミュレートし、Deep Learning Toolbox™ を使用してシミュレーション データでニューラル ネットワーク (NN) の学習を行います。

システムの説明

屋内空間に MAC アドレスが既知の信頼済みルーター (以下、既知のルーター) が複数あると仮定します。また、観察領域に未知のルーターが加わることがあり、その一部にルーター偽装者が含まれるものとします。分類 "Unknown" は、既知のセットに含まれないすべての送信元デバイスを表します。次の図は、3 台の既知のルーターがあるシナリオを示しています。オブザーバーは、それらのルーターから非高スループット (非 HT) ビーコン信号を収集し、レガシ ロング トレーニング フィールド (L-LTF) を使用して RF 指紋を識別します。送信される L-LTF 信号はすべてのルーターで同じであり、アルゴリズムによってデータ依存性が回避されます。ルーターとオブザーバーは固定であるため、RF 指紋 (マルチパス チャネル プロファイルと RF 損失の組み合わせ) の RF1、RF2、および RF3 は時間が経過しても変わりません。未知のルーターのデータは、既知のルーターとは別のランダムな RF 指紋の集合です。

次の図は、ルーターとモバイル ホット スポットに接続したユーザーを示しています。学習後、オブザーバーはビーコン フレームを受信して MAC アドレスを復号化します。さらに、オブザーバーは L-LTF 信号を抽出し、その信号を使用してビーコン フレームの送信元の RF 指紋を分類します。ルーター 1、ルーター 2、ルーター 3 の場合のように、MAC アドレスと RF 指紋が一致する場合、オブザーバーは送信元を "既知" のルーターとして宣言します。モバイル ホット スポットの場合のように、ビーコンの MAC アドレスがデータベースになく、RF 指紋が既知のルーターのいずれとも一致しない場合、オブザーバーは送信元を "未知" のルーターとして宣言します。

次の図は、ルーター偽装者の活動を示しています。ルーター偽装者 (別名 Evil Twin) は、既知のルーターの MAC アドレスを複製してビーコン フレームを送信します。その後、ハッカーは元のルーターを使用できない状態にし、ユーザーが Evil Twin に接続するように仕向けます。オブザーバーは、Evil Twin からもビーコン フレームを受信して MAC アドレスを復号化します。復号化された MAC アドレスは既知のルーターの MAC アドレスと一致しますが、RF 指紋は一致しません。オブザーバーは送信元をルーター偽装者として宣言します。

システム パラメーターの設定

各ルーターの 5,000 の非 HT WLAN ビーコン フレームで構成されるデータセットを生成します。既知のルーターについては MAC アドレスをラベルとして使用し、それ以外には "Unknown" というラベルを付けます。既知のルーターを分類して未知のルーターも検出するように NN の学習を行います。学習用、検証用、テスト用に、データセットをそれぞれ 80%、10%、10% の割合で分割します。SNR は 20 dB で、動作帯域は 5 GHz とします。シミュレートするデバイスの数は 4 に設定しますが、numKnownRouters で別の値を選択することで変更できます。未知のルーターの数を既知のルーターよりも多く設定して、未知のルーターの RF 指紋における変動性をデータセットに表現します。

numKnownRouters = 4;
numUnknownRouters = 10;
numTotalRouters = numKnownRouters+numUnknownRouters;
SNR = 20;                 % dB
channelNumber = 153;      % WLAN channel number
channelBand = 5;          % GHz
frameLength = 160;        % L-LTF sequence length in samples

この例では、既定では、学習データと学習済みネットワークを https://www.mathworks.com/supportfiles/spc/RFFingerprinting/RFFingerprintingSimulatedData.tar.gz からダウンロードします。インターネット接続がない場合は、インターネットに接続したコンピューターで手動でファイルをダウンロードし、この例のファイルと同じディレクトリに保存してください。

この例を迅速に実行するには、事前学習済みのネットワークをダウンロードし、10 個ほどの少数のフレームを生成します。コンピューターでネットワークに学習させるには、"Train network now" オプションを選択します (つまり、trainNow を true に設定します)。5000 フレームのデータを生成するには、64 MB のメモリを搭載した Intel® Xeon® W-2133 CPU @ 3.6 GHz で約 50 分かかります。このネットワークの学習にかかる時間は、NVIDIA® Titan Xp GPU で約 5 分です。CPU の場合、学習時間が非常に長くなることがあります。

trainNow = false;

if trainNow
  numTotalFramesPerRouter = 5000; %#ok<UNRCH>
else
  numTotalFramesPerRouter = 10;
  rfFingerprintingDownloadData('simulated')
end
Starting download of data files from:
	https://www.mathworks.com/supportfiles/spc/RFFingerprinting/RFFingerprintingSimulatedData.tar.gz
Download and extracting files done
  numTrainingFramesPerRouter = numTotalFramesPerRouter*0.8;
  numValidationFramesPerRouter = numTotalFramesPerRouter*0.1;
  numTestFramesPerRouter = numTotalFramesPerRouter*0.1;

WLAN 波形の生成

802.11a/g/n/ac プロトコルを実装する Wi-Fi ルーターは、ビーコン フレームを 5 GHz の帯域で送信し、その存在と機能を OFDM 非 HT フォーマットを使用してブロードキャストします。ビーコン フレームは、プリアンブル (SYNC) とペイロード (DATA) という 2 つの主要部分で構成されます。プリアンブルには短い学習と長い学習の 2 つの部分があります。この例では、各ルーターの MAC アドレスを除き、ペイロードに含まれるビットは同じです。この CNN では、プリアンブルの L-LTF の部分を学習単位として使用します。L-LTF 信号を RF 指紋に再利用することで、オーバーヘッドがない指紋ソリューションとなります。関数 wlanMACFrameConfig (WLAN Toolbox)wlanMACFrame (WLAN Toolbox)wlanNonHTConfig (WLAN Toolbox)、およびwlanWaveformGenerator (WLAN Toolbox)を使用して、WLAN ビーコン フレームを生成します。

% Create Beacon frame-body configuration object
frameBodyConfig = wlanMACManagementConfig;

% Create Beacon frame configuration object
beaconFrameConfig = wlanMACFrameConfig('FrameType', 'Beacon', ...
  "ManagementConfig", frameBodyConfig);

% Generate Beacon frame bits
[~, mpduLength] = wlanMACFrame(beaconFrameConfig, 'OutputFormat', 'bits');

% Create a wlanNONHTConfig object, 20 MHz bandwidth and MCS 1 are used
nonHTConfig = wlanNonHTConfig(...
  'ChannelBandwidth', "CBW20",...
  "MCS", 1,...
  "PSDULength", mpduLength);

rfFingerprintingNonHTFrontEnd オブジェクトは、L-LTF 信号の抽出を含むフロントエンドの処理を実行します。このオブジェクトは、20 MHz のチャネル帯域幅で非 HT 信号を処理するように構成されています。

rxFrontEnd = rfFingerprintingNonHTFrontEnd('ChannelBandwidth', 'CBW20');

fc = wlanChannelFrequency(channelNumber, channelBand);
fs = wlanSampleRate(nonHTConfig);

チャネル障害と RF 損失の設定

以下の障害があるチャネルを通して各フレームを渡します。

  • レイリー マルチパス フェージング

  • 無線損失 (位相ノイズ、周波数オフセット、DC オフセットなど)

  • AWGN

レイリー マルチパスと AWGN

チャネルは、comm.RayleighChannelSystem object™ を使用して、レイリー マルチパス フェージング チャネル経由で信号を渡します。対応する平均パス ゲインが [0 -2 -10] dB の [0 1.8 3.4] サンプルの遅延プロファイルを仮定します。チャネルは静的であるため、同じ無線に対するチャネルが変わらないように最大ドップラー シフトを 0 に設定します。以下の設定でマルチパス チャネルを実装します。ノイズの追加には関数awgnを使用します。

multipathChannel = comm.RayleighChannel(...
  'SampleRate', fs, ...
  'PathDelays', [0 1.8 3.4]/fs, ...
  'AveragePathGains', [0 -2 -10], ...
  'MaximumDopplerShift', 0);

無線損失

RF 損失とそれらに対応する値の範囲は次のとおりです。

  • 位相ノイズ: [0.01, 0.3] rms (度)

  • 周波数オフセット: [-4, 4] ppm

  • DC オフセット: [-50, -32] dBc

RF 損失のシミュレーションの詳細については、関数 helperRFImpairments を参照してください。この関数では、comm.PhaseFrequencyOffsetcomm.PhaseNoiseの System object を使用します。

phaseNoiseRange = [0.01, 0.3];
freqOffsetRange = [-4, 4];
dcOffsetRange = [-50, -32];

rng(123456)  % Fix random generator

% Assign random impairments to each simulated radio within the previously
% defined ranges
radioImpairments = repmat(...
  struct('PhaseNoise', 0, 'DCOffset', 0, 'FrequencyOffset', 0), ...
  numTotalRouters, 1);
for routerIdx = 1:numTotalRouters
  radioImpairments(routerIdx).PhaseNoise = ...
    rand*(phaseNoiseRange(2)-phaseNoiseRange(1)) + phaseNoiseRange(1);
  radioImpairments(routerIdx).DCOffset = ...
    rand*(dcOffsetRange(2)-dcOffsetRange(1)) + dcOffsetRange(1);
  radioImpairments(routerIdx).FrequencyOffset = ...
    fc/1e6*(rand*(freqOffsetRange(2)-freqOffsetRange(1)) + freqOffsetRange(1));
end

チャネル障害の適用と学習用データ フレームの生成

前に定義した RF 損失とチャネル障害を適用します。各無線のチャネル オブジェクトをリセットして独立したチャネルを生成します。受信フレームの処理には関数 rfFingerprintingNonHTFrontEnd を使用します。最後に、送信された各 WLAN フレームから L-LTF を抽出します。受信した L-LTF 信号を学習、検証、およびテストの各セットに分割します。

% Create variables that will store the training, validation and testing
% datasets
xTrainingFrames = zeros(frameLength, numTrainingFramesPerRouter*numTotalRouters);
xValFrames = zeros(frameLength, numValidationFramesPerRouter*numTotalRouters);
xTestFrames = zeros(frameLength, numTestFramesPerRouter*numTotalRouters);

% Index vectors for train, validation and test data units
trainingIndices = 1:numTrainingFramesPerRouter;
validationIndices = 1:numValidationFramesPerRouter;
testIndices = 1:numTestFramesPerRouter;

tic
generatedMACAddresses = strings(numTotalRouters, 1);
rxLLTF = zeros(frameLength, numTotalFramesPerRouter);     % Received L-LTF sequences
for routerIdx = 1:numTotalRouters
  
  % Generate a 12-digit random hexadecimal number as a MAC address for
  % known routers. Set the MAC address of all unknown routers to
  % 'AAAAAAAAAAAA'.
  if (routerIdx<=numKnownRouters)
    generatedMACAddresses(routerIdx) = string(dec2hex(bi2de(randi([0 1], 12, 4)))');
  else
    generatedMACAddresses(routerIdx) = 'AAAAAAAAAAAA';
  end
  elapsedTime = seconds(toc);
  elapsedTime.Format = 'hh:mm:ss';
  fprintf('%s - Generating frames for router %d with MAC address %s\n', ...
    elapsedTime, routerIdx, generatedMACAddresses(routerIdx))

  % Set MAC address into the wlanFrameConfig object
  beaconFrameConfig.Address2 = generatedMACAddresses(routerIdx);
  
  % Generate beacon frame bits
  beacon = wlanMACFrame(beaconFrameConfig, 'OutputFormat', 'bits');
  
  txWaveform = wlanWaveformGenerator(beacon, nonHTConfig);
  
  txWaveform = helperNormalizeFramePower(txWaveform);
  
  % Add zeros to account for channel delays
  txWaveform = [txWaveform; zeros(160,1)]; %#ok<AGROW>
  
  % Reset multipathChannel object to generate a new static channel
  reset(multipathChannel)
  
  frameCount= 0;
  while frameCount<numTotalFramesPerRouter
    
    rxMultipath = multipathChannel(txWaveform);
    
    rxImpairment = helperRFImpairments(rxMultipath, radioImpairments(routerIdx), fs);
    
    rxSig = awgn(rxImpairment,SNR,0);
    
    % Detect the WLAN packet and return the received L-LTF signal using
    % rfFingerprintingNonHTFrontEnd object
    [valid, ~, ~, ~, ~, LLTF] = rxFrontEnd(rxSig);
    
    % Save successfully received L-LTF signals
    if valid
      frameCount=frameCount+1;
      rxLLTF(:,frameCount) = LLTF;
    end
    
    if mod(frameCount,500) == 0
      elapsedTime = seconds(toc);
      elapsedTime.Format = 'hh:mm:ss';
      fprintf('%s - Generated %d/%d frames\n', ...
        elapsedTime, frameCount, numTotalFramesPerRouter)
    end
  end
  
  rxLLTF = rxLLTF(:, randperm(numTotalFramesPerRouter));
  
  % Split data into training, validation and test
  xTrainingFrames(:, trainingIndices+(routerIdx-1)*numTrainingFramesPerRouter) ...
    = rxLLTF(:, trainingIndices);
  xValFrames(:, validationIndices+(routerIdx-1)*numValidationFramesPerRouter)...
    = rxLLTF(:, validationIndices+ numTrainingFramesPerRouter);
  xTestFrames(:, testIndices+(routerIdx-1)*numTestFramesPerRouter)...
    = rxLLTF(:, testIndices + numTrainingFramesPerRouter+numValidationFramesPerRouter);
end
00:00:00 - Generating frames for router 1 with MAC address 4DA3EE3C8968
00:00:00 - Generating frames for router 2 with MAC address B1077CFE3777
00:00:00 - Generating frames for router 3 with MAC address DB28133A97BF
00:00:00 - Generating frames for router 4 with MAC address B8AF375DAC0F
00:00:01 - Generating frames for router 5 with MAC address AAAAAAAAAAAA
00:00:01 - Generating frames for router 6 with MAC address AAAAAAAAAAAA
00:00:01 - Generating frames for router 7 with MAC address AAAAAAAAAAAA
00:00:01 - Generating frames for router 8 with MAC address AAAAAAAAAAAA
00:00:02 - Generating frames for router 9 with MAC address AAAAAAAAAAAA
00:00:02 - Generating frames for router 10 with MAC address AAAAAAAAAAAA
00:00:02 - Generating frames for router 11 with MAC address AAAAAAAAAAAA
00:00:02 - Generating frames for router 12 with MAC address AAAAAAAAAAAA
00:00:02 - Generating frames for router 13 with MAC address AAAAAAAAAAAA
00:00:02 - Generating frames for router 14 with MAC address AAAAAAAAAAAA
% Label received frames. Label the first numKnownRouters with their MAC
% address. Label the rest with "Unknown”.
labels = generatedMACAddresses;
labels(generatedMACAddresses == generatedMACAddresses(numTotalRouters)) = "Unknown";

yTrain = repelem(labels, numTrainingFramesPerRouter);
yVal = repelem(labels, numValidationFramesPerRouter);
yTest = repelem(labels, numTestFramesPerRouter);

実数値の入力行列の作成

深層学習モデルは実数値でのみ機能します。そのため、I と Q が 2 つの別々の列に分割されます。その後、Deep Learning Toolbox の要件に従って、frameLength x 2 x 1 x numFrames の配列にデータが再配置されます。さらに、学習セットがシャッフルされ、ラベル変数がカテゴリカル変数として保存されます。

% Rearrange datasets into a one-column vector
xTrainingFrames = xTrainingFrames(:);
xValFrames = xValFrames(:);
xTestFrames = xTestFrames(:);

% Separate between I and Q
xTrainingFrames = [real(xTrainingFrames), imag(xTrainingFrames)];
xValFrames = [real(xValFrames), imag(xValFrames)];
xTestFrames = [real(xTestFrames), imag(xTestFrames)];

% Reshape training data into a frameLength x 2 x 1 x
% numTrainingFramesPerRouter*numTotalRouters matrix
xTrainingFrames = permute(...
  reshape(xTrainingFrames,[frameLength,numTrainingFramesPerRouter*numTotalRouters, 2, 1]),...
  [1 3 4 2]);

% Shuffle data
vr = randperm(numTotalRouters*numTrainingFramesPerRouter);
xTrainingFrames = xTrainingFrames(:,:,:,vr);

% Create label vector and shuffle
yTrain = categorical(yTrain(vr));

% Reshape validation data into a frameLength x 2 x 1 x
% numValidationFramesPerRouter*numTotalRouters matrix
xValFrames = permute(...
  reshape(xValFrames,[frameLength,numValidationFramesPerRouter*numTotalRouters, 2, 1]),...
  [1 3 4 2]);

% Create label vector
yVal = categorical(yVal);

% Reshape test dataset into a numTestFramesPerRouter*numTotalRouter matrix
xTestFrames = permute(...
  reshape(xTestFrames,[frameLength,numTestFramesPerRouter*numTotalRouters, 2, 1]),...
  [1 3 4 2]); %#ok<NASGU>

% Create label vector
yTest = categorical(yTest); %#ok<NASGU>

ニューラル ネットワークの学習

この例では、2 つの畳み込み層と 3 つの全結合層で構成されるニューラル ネットワーク (NN) アーキテクチャを使用します。この設計の背景にある洞察は、最初の層で I と Q の特徴を別々に学習することです。フィルター サイズは 1 行 7 列であることに注目してください。その後、次の層で 2 行 7 列のフィルター サイズを使用して I と Q を結合する特徴を抽出します。最後に、残りの 3 つの全結合層が前の各層で抽出された特徴を使用して分類器として動作します [1]

poolSize = [2 1];
strideSize = [2 1];
layers = [
  imageInputLayer([frameLength 2 1], 'Normalization', 'none', 'Name', 'Input Layer')
  
  convolution2dLayer([7 1], 50, 'Padding', [1 0], 'Name', 'CNN1')
  batchNormalizationLayer('Name', 'BN1')
  leakyReluLayer('Name', 'LeakyReLu1')
  maxPooling2dLayer(poolSize, 'Stride', strideSize, 'Name', 'MaxPool1')
  
  convolution2dLayer([7 2], 50, 'Padding', [1 0], 'Name', 'CNN2')
  batchNormalizationLayer('Name', 'BN2')
  leakyReluLayer('Name', 'LeakyReLu2')
  maxPooling2dLayer(poolSize, 'Stride', strideSize, 'Name', 'MaxPool2')
  
  fullyConnectedLayer(256, 'Name', 'FC1')
  leakyReluLayer('Name', 'LeakyReLu3')
  dropoutLayer(0.5, 'Name', 'DropOut1')
  
  fullyConnectedLayer(80, 'Name', 'FC2')
  leakyReluLayer('Name', 'LeakyReLu4')
  dropoutLayer(0.5, 'Name', 'DropOut2')
  
  fullyConnectedLayer(numKnownRouters+1, 'Name', 'FC3')
  softmaxLayer('Name', 'SoftMax')
  classificationLayer('Name', 'Output')
  ]
layers = 
  18×1 Layer array with layers:

     1   'Input Layer'   Image Input             160×2×1 images
     2   'CNN1'          Convolution             50 7×1 convolutions with stride [1  1] and padding [1  1  0  0]
     3   'BN1'           Batch Normalization     Batch normalization
     4   'LeakyReLu1'    Leaky ReLU              Leaky ReLU with scale 0.01
     5   'MaxPool1'      Max Pooling             2×1 max pooling with stride [2  1] and padding [0  0  0  0]
     6   'CNN2'          Convolution             50 7×2 convolutions with stride [1  1] and padding [1  1  0  0]
     7   'BN2'           Batch Normalization     Batch normalization
     8   'LeakyReLu2'    Leaky ReLU              Leaky ReLU with scale 0.01
     9   'MaxPool2'      Max Pooling             2×1 max pooling with stride [2  1] and padding [0  0  0  0]
    10   'FC1'           Fully Connected         256 fully connected layer
    11   'LeakyReLu3'    Leaky ReLU              Leaky ReLU with scale 0.01
    12   'DropOut1'      Dropout                 50% dropout
    13   'FC2'           Fully Connected         80 fully connected layer
    14   'LeakyReLu4'    Leaky ReLU              Leaky ReLU with scale 0.01
    15   'DropOut2'      Dropout                 50% dropout
    16   'FC3'           Fully Connected         5 fully connected layer
    17   'SoftMax'       Softmax                 softmax
    18   'Output'        Classification Output   crossentropyex

ミニバッチ サイズが 256 の ADAM オプティマイザーを使用するように学習オプションを構成します。既定では、'ExecutionEnvironment' は 'auto' に設定されており、利用可能な場合は GPU が学習に使用されます。そうでない場合、trainNetwork (Deep Learning Toolbox)では CPU が学習に使用されます。実行環境を明示的に設定するには、'ExecutionEnvironment' を 'cpu'、'gpu'、'multi-gpu'、または 'parallel' のいずれかに設定します。'cpu' を選択すると、学習時間が非常に長くなることがあります。

if trainNow
  
  miniBatchSize = 256; %#ok<UNRCH>
  
  % Training options
  options = trainingOptions('adam', ...
    'MaxEpochs',100, ...
    'ValidationData',{xValFrames, yVal}, ...
    'ValidationFrequency',floor(numTrainingFramesPerRouter*numTotalRouters/miniBatchSize/3), ...
    'Verbose',false, ...
    'L2Regularization', 0.0001, ...
    'InitialLearnRate', 0.0001, ...
    'MiniBatchSize', miniBatchSize, ...
    'ValidationPatience', 3, ...
    'Plots','training-progress', ...
    'Shuffle','every-epoch');
  
  % Train the network
  simNet = trainNetwork(xTrainingFrames, yTrain, layers, options);
else
  % Load trained network (simNet), testing dataset (xTestFrames and
  % yTest) and the used MACAddresses (generatedMACAddresses)
  load('rfFingerprintingSimulatedDataTrainedNN.mat',...
    'generatedMACAddresses',...
    'simNet',...
    'xTestFrames',...
    'yTest')
end

学習の進行状況のプロットで示されているように、このネットワークは約 2 エポックでほぼ 100% の精度に収束します。

テスト フレームを分類し、ニューラル ネットワークの最終的な精度を計算します。

% Obtain predicted classes for xTestFrames
yTestPred = classify(simNet,xTestFrames);

% Calculate test accuracy
testAccuracy = mean(yTest == yTestPred);
disp("Test accuracy: " + testAccuracy*100 + "%")
Test accuracy: 100%

テスト フレームの混同行列をプロットします。前述のとおり、合成データセットで完全な分類の正確性が達成されます。

figure
cm = confusionchart(yTest, yTestPred);
cm.Title = 'Confusion Matrix for Test Data';
cm.RowSummary = 'row-normalized';

ルーター偽装者の検出

既知の MAC アドレスと 1 つの未知の MAC アドレスでビーコン フレームを生成します。一連の新しい RF 損失とマルチパス チャネルを生成します。損失はすべて新しいものであるため、それらのフレームの RF 指紋は "Unknown" と分類されるはずです。既知の MAC アドレスのフレームはルーター偽装者を表しますが、未知の MAC アドレスのフレームは単純に不明なルーターです。

framesPerRouter = 4;
knownMACAddresses = generatedMACAddresses(1:numKnownRouters);

% Assign random impairments to each simulated radio within the previously
% defined ranges
for routerIdx = 1:numTotalRouters
  radioImpairments(routerIdx).PhaseNoise = rand*( phaseNoiseRange(2)-phaseNoiseRange(1) ) + phaseNoiseRange(1);
  radioImpairments(routerIdx).DCOffset = rand*( dcOffsetRange(2)-dcOffsetRange(1) ) + dcOffsetRange(1);
  radioImpairments(routerIdx).FrequencyOffset = fc/1e6*(rand*( freqOffsetRange(2)-freqOffsetRange(1) ) + freqOffsetRange(1));
end
% Reset multipathChannel object to generate a new static channel
reset(multipathChannel)

% Run for all known routers and one unknown
for macIndex = 1:(numKnownRouters+1)
  
  beaconFrameConfig.Address2 = generatedMACAddresses(macIndex);
  
  % Generate Beacon frame bits
  beacon = wlanMACFrame(beaconFrameConfig, 'OutputFormat', 'bits');
  
  txWaveform = wlanWaveformGenerator(beacon, nonHTConfig);
  
  txWaveform = helperNormalizeFramePower(txWaveform);
  
  % Add zeros to account for channel delays
  txWaveform = [txWaveform; zeros(160,1)]; %#ok<AGROW>
  
  % Create an unseen multipath channel. In other words, create an unseen
  % RF fingerprint.
  reset(multipathChannel)
  
  frameCount= 0;
  while frameCount<framesPerRouter
    
    rxMultipath = multipathChannel(txWaveform);
    
    rxImpairment = helperRFImpairments(rxMultipath, radioImpairments(routerIdx), fs);
    
    rxSig = awgn(rxImpairment,SNR,0);
    
    % Detect the WLAN packet and return the received L-LTF signal using
    % rfFingerprintingNonHTFrontEnd object
    [payloadFull, cfgNonHT, rxNonHTData, chanEst, noiseVar, LLTF] = ...
      rxFrontEnd(rxSig);
    
    if payloadFull
      frameCount = frameCount+1;
      recBits = wlanNonHTDataRecover(rxNonHTData, chanEst, ...
        noiseVar, cfgNonHT, 'EqualizationMethod', 'ZF');
      
      % Decode and evaluate recovered bits
      mpduCfg = wlanMPDUDecode(recBits, cfgNonHT);
      
      % Separate I and Q and reshape for neural network
      LLTF= [real(LLTF), imag(LLTF)];
      LLTF = permute(reshape(LLTF,frameLength ,[] , 2, 1), [1 3 4 2]);
      
      ypred = classify(simNet, LLTF);
      
      if sum(contains(knownMACAddresses, mpduCfg.Address2)) ~= 0
        if categorical(convertCharsToStrings(mpduCfg.Address2))~=ypred
          disp(strcat("MAC Address ", mpduCfg.Address2," is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED"))
        else
          disp(strcat("MAC Address ", mpduCfg.Address2," is known, fingerprint match"))
        end
      else
        disp(strcat("MAC Address ", mpduCfg.Address2," is not recognized, unknown device"))
      end
    end

    % Reset multipathChannel object to generate a new static channel
    reset(multipathChannel)
  end
end
MAC Address 09C551658660 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address 09C551658660 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address 09C551658660 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address 09C551658660 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address CDECF20C29CA is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address CDECF20C29CA is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address CDECF20C29CA is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address CDECF20C29CA is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address DF56A9E15405 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address DF56A9E15405 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address DF56A9E15405 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address DF56A9E15405 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address EDC4537D86B1 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address EDC4537D86B1 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address EDC4537D86B1 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address EDC4537D86B1 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address AAAAAAAAAAAA is not recognized, unknown device
MAC Address AAAAAAAAAAAA is not recognized, unknown device
MAC Address AAAAAAAAAAAA is not recognized, unknown device
MAC Address AAAAAAAAAAAA is not recognized, unknown device

その他の調査

以下を変更することで、別のチャネル障害や RF 損失でシステムをテストできます。

  • マルチパス プロファイル (レイリー チャネル オブジェクトの PathDelays プロパティと AveragePathGains プロパティ)

  • チャネル ノイズ レベル (関数 awgn の SNR 入力)

  • RF 損失 (変数 phaseNoiseRangefreqOffsetRange、および dcOffsetRange)

また、以下を変更することでニューラル ネットワークの構造を変更できます。

  • 畳み込み層のパラメーター (フィルター サイズ、フィルター数、パディング)

  • 全結合層の数

  • 畳み込み層の数

付録: 補助関数

function [impairedSig] = helperRFImpairments(sig, radioImpairments, fs)
% helperRFImpairments Apply RF impairments
%   IMPAIREDSIG = helperRFImpairments(SIG, RADIOIMPAIRMENTS, FS) returns signal
%   SIG after applying the impairments defined by RADIOIMPAIRMENTS
%   structure at the sample rate FS.

% Apply frequency offset
fOff = comm.PhaseFrequencyOffset('FrequencyOffset', radioImpairments.FrequencyOffset,  'SampleRate', fs);

% Apply phase noise
phaseNoise = helperGetPhaseNoise(radioImpairments);
phNoise = comm.PhaseNoise('Level', phaseNoise, 'FrequencyOffset', abs(radioImpairments.FrequencyOffset));

impFOff = fOff(sig);
impPhNoise = phNoise(impFOff);

% Apply DC offset
impairedSig = impPhNoise + 10^(radioImpairments.DCOffset/10);

end

function [phaseNoise] = helperGetPhaseNoise(radioImpairments)
% helperGetPhaseNoise Get phase noise value
load('Mrms.mat','Mrms','MyI','xI');
[~, iRms] = min(abs(radioImpairments.PhaseNoise - Mrms));
[~, iFreqOffset] = min(abs(xI - abs(radioImpairments.FrequencyOffset)));
phaseNoise = -abs(MyI(iRms, iFreqOffset));
end

参考文献

[1] K. Sankhe, M. Belgiovine, F. Zhou, S. Riyaz, S. Ioannidis and K. Chowdhury, "ORACLE: Optimized Radio clAssification through Convolutional neuraL nEtworks," IEEE INFOCOM 2019 - IEEE Conference on Computer Communications, Paris, France, 2019, pp. 370-378.

関連するトピック