C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: C#のrawソケットでパケットキャプチャ後にブロックする方法


(過去ログ 47 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■25740 / inTopicNo.1)  C#のrawソケットでパケットキャプチャ後にブロックする方法
  
□投稿者/ きん (1回)-(2008/09/25(Thu) 12:33:28)

分類:[C#] 

Microsoft Windows XP SP2
Microsoft .NET Framework 3.0
Microsoft Visual Studio 2005 Standard Edition(C#)

こんにちは。
C#で、以下の目的を達成するツールを書こうと思っています。

・特定のURL(複数)へのアクセスをブロックしたい
・禁止URLリストに該当するURLへの接続を発見次第、警告を出したい
・(可能であれば)警告のみならず、そのアクセスを無効にしたい

このために、rawソケットを使ってパケットをキャプチャし、禁止URLを発見するところまでは動きました。このあと、可能であれば禁止URLへのパケット(HTTPリクエスト)自体を破棄したいのですが、どなたか良い方法をご存知の方がいらっしゃいましたらご教授いただけないでしょうか。

参考までに、ソースコードの抜粋を記載します。



----- ソースコード(抜粋)ここから -------------------------------------

/// <summary>
/// 危険なURLのリスト
/// </summary>
string[] targetUrlList = {
  @"xxx.yyy.com",
  @"xxx.yyy.co.jp",
  @"xxx.yyy.net"
};

// ソケットの生成
socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Bind(new IPEndPoint(IPAddress.Parse(this.IP), 0));

// ソケットの初期設定
socket.SetSocketOption(
  SocketOptionLevel.IP,
  SocketOptionName.HeaderIncluded,
  true
);
socket.IOControl(
  IOControlCode.ReceiveAll,
  byTrue,
  byOut
);

// キャプチャ開始
IAsyncResult result = socket.BeginReceive(
  state.buffer,
  0,
  StateObject.BufferSize,
  0,
  new AsyncCallback(ReceiveCallback),
  state
);

/// <summary>
/// 受信用メソッド
/// </summary>
/// <param name="ar"></param>
private static void ReceiveCallback(IAsyncResult ar)
{
  // データの取得
  int bytesRead = currentsocket.EndReceive(ar);

  // 解析
  if (bytesRead > 0)
  {
    // IPヘッダ部分
    StringBuilder ipHeader = new StringBuilder();
    foreach (byte b in currentstate.buffer)
    {
      string s = b.ToString("X");
      string str2 = Convert.ToString(b, 2);
      string str3 = String.Format("{0:D8}", Convert.ToInt32(str2));
      ipHeader.Append(str3);
    }
    int version = Convert.ToInt32(ipHeader.ToString().Substring(0, 4), 2);
    int headerLength = Convert.ToInt32(ipHeader.ToString().Substring(3, 4), 2);
    int serviceType = Convert.ToInt32(ipHeader.ToString().Substring(8, 8), 2);
    int dataGramLength = Convert.ToInt32(ipHeader.ToString().Substring(16, 16), 2);
    int id = Convert.ToInt32(ipHeader.ToString().Substring(32, 16), 2);
    int flag = Convert.ToInt32(ipHeader.ToString().Substring(48, 3), 2);
    int flagmentOffset = Convert.ToInt32(ipHeader.ToString().Substring(51, 13), 2);
    int ttl = Convert.ToInt32(ipHeader.ToString().Substring(64, 8), 2);
    int protocolNo = Convert.ToInt32(ipHeader.ToString().Substring(72, 8), 2);
    int checkSum = Convert.ToInt32(ipHeader.ToString().Substring(80, 16), 2);
    int offset = 0;
    int ipFrom1 = Convert.ToInt32(ipHeader.ToString().Substring(96 + offset, 8), 2);
    int ipFrom2 = Convert.ToInt32(ipHeader.ToString().Substring(104 + offset, 8), 2);
    int ipFrom3 = Convert.ToInt32(ipHeader.ToString().Substring(112 + offset, 8), 2);
    int ipFrom4 = Convert.ToInt32(ipHeader.ToString().Substring(120 + offset, 8), 2);
    int ipTo1 = Convert.ToInt32(ipHeader.ToString().Substring(128 + offset, 8), 2);
    int ipTo2 = Convert.ToInt32(ipHeader.ToString().Substring(136 + offset, 8), 2);
    int ipTo3 = Convert.ToInt32(ipHeader.ToString().Substring(144 + offset, 8), 2);
    int ipTo4 = Convert.ToInt32(ipHeader.ToString().Substring(152 + offset, 8), 2);
    StringBuilder ipFrom = new StringBuilder();
    ipFrom.Append(ipFrom1);
    ipFrom.Append(@".");
    ipFrom.Append(ipFrom2);
    ipFrom.Append(@".");
    ipFrom.Append(ipFrom3);
    ipFrom.Append(@".");
    ipFrom.Append(ipFrom4);
    StringBuilder ipTo = new StringBuilder();
    ipTo.Append(ipTo1);
    ipTo.Append(@".");
    ipTo.Append(ipTo2);
    ipTo.Append(@".");
    ipTo.Append(ipTo3);
    ipTo.Append(@".");
    ipTo.Append(ipTo4);

    // データ部分
    StringBuilder receivedString = new StringBuilder();
    string strMS932 = Encoding.UTF8.GetString(currentstate.buffer);
    byte[] bytesUicode = Encoding.UTF8.GetBytes(strMS932);
    foreach (byte b in bytesUicode)
    {
      string s = b.ToString("X");
      receivedString.Append(StringUtility.FromAsciiCodeEx(s));
    }
    string data = receivedString.ToString();
    
    // 再取得
    if (!currentstate.closed)
    {
      currentsocket.BeginReceive(
        currentstate.buffer,
        0,
        StateObject.BufferSize,
        0,
        new AsyncCallback(ReceiveCallback),
        currentstate
      );
    }

    // HTTP/HTTPSプロトコル以外は無視
    if (IpPacket.GetProtocol(data) == IpPacket.Protocol.Other)
      return;

    // データをセット
    IpPacket packet = IpPacket.FromRealPacket(
      ipFrom.ToString(),
      ipTo.ToString(),
      data
    );

    // 危険なら警告
    for (int i = 0; i < targetUrlList.Length; i++)
    {
      if (packet.URL.Contains(targetUrlList[i]))
      {
        // TODO: 本当はこのあたりでこのHTTPリクエストを無効にしたい
        // TODO: 本当はこのあたりでこのHTTPリクエストを無効にしたい
        // TODO: 本当はこのあたりでこのHTTPリクエストを無効にしたい
        // TODO: 本当はこのあたりでこのHTTPリクエストを無効にしたい
        // TODO: 本当はこのあたりでこのHTTPリクエストを無効にしたい
      }
    }

    // 表示
    Debug.WriteLine(packet.ToString());
  }
}
引用返信 編集キー/
■25766 / inTopicNo.2)  Re[1]: C#のrawソケットでパケットキャプチャ後にブロックする方法
□投稿者/ 黒龍 (124回)-(2008/09/25(Thu) 16:47:40)
発想はいいと思うのですが実運用するとなると負荷等気になりますね。
全パケットキャプチャというのがなかなか難しいこととそこに処理をはさむとのことなので・・・。
無効にするならRSTパケットを投げればいいですし警告等を出したいのであればリダイレクトやHTTPを中身つきで返すなどの手段が間がえられます。
が、やはりHTTPならHTTPに絞った方法(HTTP ProxyやDNS)などを使用するのがシンプルかつ効率的な気がします。実装方法としてはまったく変わってしまいますが・・・。

引用返信 編集キー/
■25789 / inTopicNo.3)  Re[2]: C#のrawソケットでパケットキャプチャ後にブロックする方法
□投稿者/ 渋木宏明(ひどり) (898回)-(2008/09/26(Fri) 00:10:33)
渋木宏明(ひどり) さんの Web サイト
> 発想はいいと思うのですが実運用するとなると負荷等気になりますね。

もそうだし、端末の管理者権限をもったユーザ相手にはひどく効果が薄い(=監視プログラムを強制終了できてしまう等)ですね。

で、管理者権限を持っていないユーザが相手だとするなら

> が、やはりHTTPならHTTPに絞った方法(HTTP ProxyやDNS)などを使用するのがシンプルかつ効率的な気がします。実装方法としてはまったく変わってしまいますが・・・。

のような手法の方が手軽で融通も効きますね。

引用返信 編集キー/
■25792 / inTopicNo.4)  Re[2]: C#のrawソケットでパケットキャプチャ後にブロックする方法
□投稿者/ きん (2回)-(2008/09/26(Fri) 09:28:24)
みなさま、お返事ありがとうございます。

やっぱり負荷的に難しそうですね。

パケットを監視し、警告を出す程度にしておきます。

プロキシサーバの自作も考えましたが、端末のブラウザの設定を変えるのがポリシ的に厳しく、断念しました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -