C# 、
OpenSSLを使用して禁止リソースのレジストリを取得し、
MikroTik機器に基づく
RouterOSを使用してフィルタリングする
自動化
注意! 2014年3月19日の最近の変更に応じて変更された記事入門
仕事では
、通信事業者のリマインダーによって導かれます。
作業は次のポイントで構成されています。
- リクエスト作成
- OpenSSLをインストールして構成する
- リクエスト署名
- リクエストの送信とリクエストの処理結果の取得
- 結果処理
- MikroTikのフィルターに追加する
リクエスト作成
レジストリからアンロードを受信する要求を送信するには、
XML形式の要求ファイルを添付する必要があり
ます 。 ファイルは次のようになります。
<?xml version="1.0" encoding="windows-1251"?> <request> <requestTime>2012-01-01T01:01:01.000+04:00</requestTime> <operatorName><![CDATA[ ]]></operatorName> <inn>1234567890</inn> <ogrn>1234567890123</ogrn> <email>email@email.ru</email> </request>
- requestTime-タイムゾーンを使用したリクエスト形成の日時。
- operatorName-通信オペレーターのフルネーム。
- inn-通信事業者のTIN(法人の場合は10桁、個々の起業家の場合は12桁);
- ogrn-通信事業者のOGRN(法人の場合は13桁、個々の起業家の場合は15桁);
- 電子メール -アンロードメカニズムの使用を担当する技術専門家の電子メールアドレス。 5月
技術的な問題や問題が発生した場合の迅速なフィードバックに使用されます。 オプションのパラメーター。
主な
ことは 、
2012-01-01T01:01:01.000 + 04:00の形式で時間を取得し、
windows-1251エンコードでファイルを保存することです。
C#のリクエスト生成関数のコード:
public static String GeneratingRequest(String operatorName, String inn, String ogrn, String email) { String result = "<?xml version=\"1.0\" encoding=\"windows-1251\"?>"; result += "<request><requestTime>"; result += DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz"); result += "</requestTime><operatorName>"; result += "<![CDATA[" + operatorName + "]]>"; result += "</operatorName><inn>"; result += inn; result += "</inn><ogrn>"; result += ogrn; result += "</ogrn><email>"; result += email; result += "</email></request>"; return result; }
次に、ファイルを
windows-1251エンコードで保存します。
String Request = GeneratingRequest(" ", "1234567890", "1234567890123", "email@email.ru") StreamWriter swRequest = new StreamWriter(@"C:\request.xml", false, Encoding.GetEncoding("Windows-1251")); swRequest.Write(Request); swRequest.Close();
リクエストを作成したら、署名する必要があります。 これを行うには、
SSL / TLS -
OpenSSLを操作するためのオープンソース暗号化パッケージを使用し
ます 。 インストールして構成します。
Openssl
このサイト
-slproweb.comからパッケージをダウンロードします。 私の場合、
Win64 OpenSSL v1.0.1gでした 。
はい、このアセンブリには
Visual C ++ 2008 Redistributablesがインストールされている必要があり、そこからダウンロードできます。
インストール。
「追加タスクの選択」ダイアログ
でインストールする場合
、 「The OpenSSL」バイナリ(/ bin)ディレクトリを選択
する必要があります。これ以上のトリックはありません。
次に、インストールしたフォルダー
C:/ OpenSSL / binに移動して、
openssl.cfgファイルを編集します。 ファイルの先頭に追加します。
openssl_conf = openssl_def
最後に:
[openssl_def]
engines=engine_section
[engine_section]
gost=gost_section
[gost_section]
engine_id=gost
dynamic_path = C:/OpenSSL/bin/gost.dll
default_algorithms=ALL
実際にはすべてがすでに機能していますが、環境変数を設定することは残っています:
OPENSSL_CONF = C:/OpenSSL/bin/openssl.cfg-openssl.cfgへの
フルパスさて、
PATH + = C:/ OpenSSL / bin;次に、EDSが必要です。
信頼できる証明機関で購入できます。 キーは、
P12FromGostCSPユーティリティを使用して、Windowsの
暗号コンテナーから
PKCS#12形式でエクスポートする必要があります。
なぜP12FromGostCSPLinuxでのPhp-soapインタラクションとGOSTアルゴリズムを使用した証明書認証からの
xtronのコメントを
引用一見するとすべてが単純であるとは限りません。 実際、標準の証明書表示ダイアログからエクスポートされた証明書は、opensslで認識されません。 次のエラーが判明します。
MAC確認済みOK
バッグの属性
localKeyID:01 00 00 00
friendlyName:レジストリ\\ mstaff
Microsoft CSP名:Crypto-Pro GOST R 10/34/2001 Cryptographic Service Provider
キーと証明書の出力エラー
140017040754368:エラー:06074079:デジタルエンベロープルーチン:EVP_PBE_CipherInit:不明なpbeアルゴリズム:evp_pbe.c:167:TYPE = 1.2.840.113549.1.12.1.80
140017040754368:エラー:23077073:PKCS12ルーチン:PKCS12_pbe_crypt:pkcs12 algor cipherinitエラー:p12_decr.c:83:
140017040754368:エラー:2306A075:PKCS12ルーチン:PKCS12_item_decrypt_d2i:pkcs12 pbe暗号化エラー:p12_decr.c:130:
これがこのユーティリティであり、このようなエラーを回避できます。 このユーティリティの開発者を引用します。
P12FromGostCSPユーティリティによって作成されたPKCS#12コンテナーは、CryptoCom LLC(opensslプロジェクトの一部)およびTop Cross LLCによって作成された類似のコンテナーと完全に互換性があります。残念ながら、CryptoProに含まれるソフトウェアツールによって作成されたコンテナーについては言えませんCSP(バージョンR3以降)。
次のタイプのopensslまたはlirsslユーティリティを使用して、CryptoPro CSP R3ツールによって作成されたPKCS#12コンテナーおよび他の手段によって作成されたコンテナーのASN1構造を表示すると便利です。
#openssl asn1parse –inform DER –in <PKCS container#12>
これらの構造を比較すると、たとえば、ハッシュアルゴリズムGOST R 34.11-94の代わりに、CryptoProのコンテナーでSHA1が使用されていることがすぐにわかります。 次のコマンドを実行してコンテナの内容を表示しようとすると、さらに興味深い結果が得られます。
#openssl pkcs12 –in <PKCSコンテナー#12>
PKCS#12ファイルには、証明書と秘密キーが含まれている必要があります! 次のコマンドでこれを確認できます。
openssl.exe pkcs12 -in C:/key.pfx -nodes

次に、それを
PEMに変換します。
OpenSSLでは、これは次のように行われます(コマンドラインから
-PKCS#12キーを保護するパスワードを要求できます)。
openssl.exe pkcs12 -in C:/key.pfx -out C:/key.pem -nodes -clcerts

これで、誰もがリクエストに署名できるようになりました。
署名をリクエスト
次のコマンドを使用して、OpenSSLを介してリクエストに署名できます。
openssl.exe smime -sign -in C:/request.xml -out C:/request.xml.sign -signer C:/key.pem -outform DER

C#でのファイル署名機能の実装:
public static Boolean SignRequest() { Boolean ret = true; String OpenSSLPath = @"C:\OpenSSL\bin"; String RequestPath = @"C:\request.xml"; String SignRequestPath = @"C:\request.xml.sign"; String KeyPEMPath = @"C:\key.pem"; try { Process cmdProcess = new Process(); cmdProcess.StartInfo.WorkingDirectory = OpenSSLPath; cmdProcess.StartInfo.FileName = "openssl.exe"; cmdProcess.StartInfo.Arguments = String.Format("smime -sign -in {0} -out {1} -signer {2} -outform DER", RequestPath, SignRequestPath, KeyPEMPath); cmdProcess.StartInfo.CreateNoWindow = true; cmdProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; cmdProcess.Start();
では、作業を確認してください。
電子 署名の 認証 :
gosuslugi.ru 、選択-
電子文書の真正性の確認。 ES-切断済み、PKCS#7形式OpenSSLを使用して確認できますが、そのためには、発行者の証明書を抽出する必要があります。これにより、EDSが提供され、PEM形式に変換されます(証明書は
ここで取得でき
ます )。
openssl x509 -inform der -in C:/most.cer -out C:/most.pem
そして署名を確認してください:
openssl.exe smime -verify -in C:/request.xml.sign -content C:/request.xml -CAfile C:/most.pem -inform DER -out C:/validrequest.xml
その結果、次の行が表示されます。
Verification successful
また、
request.xmlのコンテンツは
validrequest.xmlファイルに
含まれます。
禁止されているリソースのレジストリのダンプのリクエストに直接進みます。
リクエストを送信してレジストリをアップロードする
すべてが手動で簡単です:
要求送信
フォーム 、要求ファイルとその署名(
C:/request.xmlおよび
C:/request.xml.sign )を送信します

すべてが正常な場合、結果は-要求IDになります。これを使用して、要求の処理結果を確認できます。 原則として、すべてが正常であれば、アーカイブに5分後に
ZIP形式でレジストリがアンロードされます。2つの
dump.xmlファイル (レジストリダンプとそのデジタル署名)があります。
OpenSSLまたは
gosuslugi.ruでファイルを確認できます。
openssl.exe smime -verify -in C:/dump.xml.sig -content C:/dump.xml -CAfile C:/cartk.pem -inform DER -out C:/validdump.xml
その結果、次の行が表示されます。
Verification successful
そして、
dump.xmlの内容は
validdump.xmlファイルにあります 。
次に、このプロセスを自動化します。 アンロードには、
SOAPアクセス
プロトコル 、アドレス:
serviceで動作するサービスがあり
ます 。
WSDLスキームは、
WSDLスキームで入手できます。
サービスは4つのメソッドで構成されています。
- getLastDumpDateEx
このメソッドは、レジストリからアップロードの最終更新のタイムスタンプを取得することを目的としています。 応答として、 lastDumpDateを送信します - 長い日付はUNIXタイムスタンプ形式ですが、秒単位ではなくミリ秒単位で、 lastDumpDateUrgentlyになります -即時応答を必要とするアップロードが最後に変更された時刻 ( UNIXタイムスタンプ形式でも来ます) 、ただし、秒単位ではなく、ミリ秒単位で)。 - getLastDumpDate
互換性のために残しました。 getLastDumpDateExに似ていますが、1つのパラメーターlastDumpDateのみを返します。 長い日付はUNIXタイムスタンプ形式ですが、秒単位ではなくミリ秒単位で返されます。 - sendRequest
このメソッドは、レジストリからアンロードを受信するためのリクエストを送信するように設計されていますbase64Binary形式のrequestFileとsignatureFileを受け入れます-リクエストファイルとその署名( C:/request.xmlおよびC:/request.xml.sign )応答で、 結果を送信します-リクエストの処理結果ブール形式、すべてが成功した場合、 コード -要求識別子、レジストリから文字列形式でアンロードを取得する必要がある行。 またresultComment-リクエストを文字列形式で処理した結果に関するコメント。 - getResult
このメソッドは、リクエストの処理結果を取得するように設計されています -レジストリからのアンロード、 コードの取得 -リクエスト識別子、レジストリからのアンロードを文字列形式で取得する必要がある行。 応答として、彼は結果を送信します- ブール形式でリクエストを処理した結果、そしてすべてが成功した場合、 registerZipArchive - base64Binary形式でレジストリからアンロードするファイルzipアーカイブ 。 またresultComment-リクエストを文字列形式で処理した結果に関するコメント。
resultCommentタグに指定できる値:
- リクエストは処理中です
- 無効なESアルゴリズム
- 無効なES形式
- 無効なES証明書
- EPの誤った値
- ES証明書検証エラー
- 申請者は、情報および通信ネットワークへのアクセスを提供するためのサービスを提供する権利を付与するライセンスを持っていませんインターネット
問題を解決するためのフィードバック情報は、
このセクションのキャリアへのメモに記載されています。
サービスを操作するロジック:
- レジストリからのアンロードが更新されたかどうかを確認してください。 これを行うには、 getLastDumpDateExメソッドを呼び出して、取得した値を前の反復で取得した値と比較します。 lastDumpDateUrgentlyの値が変更された場合は、すぐに更新されたアンロードを要求してください。 それ以外の場合、裁量でアンロードを更新しますが、少なくとも1日に1回は更新します。
- アンロードが更新された場合、 sendRequestメソッドを使用してアンロードのリクエストを送信します。
- 数分後、 getResultメソッドを呼び出して、リクエストの処理結果を取得します。 要求がまだ処理されていない場合( resultCommentフィールドの内容を参照)、数分後に手順3を繰り返します。
サービスをリソースに追加し、WSDLスキームのアドレスを渡します。
機能コード
getLastDumpDate 、
sendRequest 、
getResultMaxReceivedMessageSize最近、フォームのエラーが表示されるようになりました。着信メッセージの最大メッセージサイズのクォータを超えました(
65536 )。 クォータを増やすには、対応するバインディング要素の
MaxReceivedMessageSizeプロパティを使用します。
したがって、
MaxReceivedMessageSizeプロパティを増やす
必要がありました。
サポートコメント:
現時点では、getResultメソッドの応答には、サイズが65536バイトよりわずかに大きいxmlデータブロックが含まれています。
public static Int64 LastDumpDate() { Int64 lastDumpDate = 0; BasicHttpBinding HttpBinding = new BasicHttpBinding(); HttpBinding.MaxReceivedMessageSize = 1*1024*1024*1024;
たとえば、リクエストを送信します。
String resultComment, code; if(SendRequest(out resultComment, out code, File.ReadAllBytes(@"C:/request.xml"), File.ReadAllBytes(@"C:/request.xml.sign"))) {
レジストリからアンロードするための最後の更新のタイムスタンプは、次のようにUNIXタイムスタンプからDateTimeに変換できます。
DateTime LastDumpDate = (new DateTime(1970, 1, 1, 0, 0, 0, 0)).AddSeconds(LastDumpDate()/1000);
レジストリダンプを解析する
アーカイブを解凍する必要があります。
その結果、レジストリダンプ
Cを取得します
:/register/dump.xmlダンプの内容の例:
<?xml version="1.0" encoding="windows-1251"?> <reg:register updateTime="2014-02-02T12:00:00+04:00" xmlns:reg="http://rsoc.ru" xmlns:tns="http://rsoc.ru" updateTimeUrgently="2014-02-01T11:00:00"> <content id="68" includeTime="2013-12-01T10:00:05"> <decision date="2013-12-01" number="9" org=""/> <url><![CDATA[http://site1.com/index.php]]></url> <domain><![CDATA[site1.com]]></domain> <ip>1.1.1.1</ip> </content> <content id="68" includeTime="2013-12-01T10:00:05"> <decision date="2013-12-01" number="9" org=""/> <url><![CDATA[http://site2.com/page1.php]]></url> <url><![CDATA[http://site2.com/page2.php]]></url> <url><![CDATA[http://site2.com/page3.php]]></url> <domain><![CDATA[site2.com]]></domain> <ip>1.1.1.1</ip> <ip>1.1.1.2</ip> </content> <content id="9999" includeTime="2014-02-01T15:17:51" urgencyType="1"> <decision date="2014-02-01" number=" " org=""/> <url><![CDATA[http://site3.com/page1.html]]></url> <domain><![CDATA[site3.com]]></domain> <ip>1.2.3.4</ip> </content> </reg:register>
Parsim XML
これを行うには、2つのクラスを作成します。最初の
RegisterDumpには
UpdateTimeフィールドと
コンテンツオブジェクトのリストが含まれ、2番目の
ItemRegisterDumpはすべてのフィールドを持つ1つの
コンテンツオブジェクトを表します。
public class RegisterDump { public List<ItemRegisterDump> Items { get; set; } public String UpdateTime { get; set; } public RegisterDump() { this.Items = new List<ItemRegisterDump>(); this.UpdateTime = String.Empty; } public RegisterDump(String UpdateTime, List<ItemRegisterDump> Items) { this.Items = Items; this.UpdateTime = UpdateTime; } } public class ItemRegisterDump { public String id { get; set; } public String includeTime { get; set; } public String date { get; set; } public String number { get; set; } public String org { get; set; } public List<String> url { get; set; } public List<String> domain { get; set; } public List<String> ip { get; set; } public ItemRegisterDump() { id = String.Empty; includeTime = String.Empty; date = String.Empty; number = String.Empty; org = String.Empty; url = new List<String>(); domain = new List<String>(); ip = new List<String>(); } }
パーシム:
RegisterDump Register = new RegisterDump(); String dumpfile = @"C:/register/dump.xml"; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(dumpfile); Register.UpdateTime = xmlDoc.GetElementsByTagName("reg:register")[0].Attributes.GetNamedItem("updateTime").InnerText; XmlNodeList content = xmlDoc.GetElementsByTagName("content"); for (int i = 0; i < content.Count; i++) { ItemRegisterDump item = new ItemRegisterDump(); item.id = content[i].Attributes.GetNamedItem("id").InnerText; item.includeTime = content[i].Attributes.GetNamedItem("includeTime").InnerText; foreach (XmlNode node in content[i].ChildNodes) { switch(node.Name) { case "decision": item.date = node.Attributes.GetNamedItem("date").InnerText; item.number = node.Attributes.GetNamedItem("number").InnerText; item.org = node.Attributes.GetNamedItem("org").InnerText; break; case "url": item.url.Add(node.InnerText); break; case "domain": item.domain.Add(node.InnerText); break; case "ip": item.ip.Add(node.InnerText); break; } } Register.Items.Add(item); }
MikroTikでこれらすべてをブロックします。
MikroTikによるブロッキング
layer7-protocolを使用してこれを
行い 、
フィルターに追加します。
以下に例を示します。
/ip firewall layer7-protocol add name=12 comment=register regexp=^.+(chelaxe.ru).*$
/ip firewall filter add action=drop chain=forward disabled=no dst-port=80 layer7-protocol=12 protocol=tcp src-address=192.168.0.0/24 comment=register




これで、サブストリング
chelaxe.ruの内容を持つ
TCPを介してポート
80に到着する
192.168.0.0/24サブネットのすべてのパケット
が破棄されます。
コメントでは、碑文
登録は簡単に追加されません。 更新されたルールを追加する前に、すべてのルールを削除する必要があります。
すべてのエントリを削除するスクリプトを次に示します。
/ip firewall layer7-protocol remove [find comment=register]
/ip firewall filter remove [find comment=register]

MikroTikルーターとの通信は
APIを介して行われ
ますが 、すでに必要なライブラリを例とともに作成してい
ます :
wiki / API C#このライブラリ(クラス)と上記で解析されたコンテンツをブロックする原理を使用して、これをすべてC#で実装します。
public static Boolean AddFilterL7(String ip, String username, String password, RegisterDump dump, String SRCAddress) { Boolean ret = true; try {
この例では、ドメインブロッキングを使用しましたが、これは完全に真実ではありません。 URLでブロックするには、
layer7-protocolに次の正規表現を使用でき
ます 。
^.*(/summary).*(chelaxe.ru).*$
さらに、
MikroTikエラーの結果として、5番目のブランチからのRouterOSのバージョンを使用する場合、式は小文字でなければなりません。
ソースは
こちらから入手でき
ます 。
作成がガイドされたとき:
キャリアメモOpenSSL 1.0.1c + libGOST.so + CryptoPro + ruTokenのキー禁止されているリソースレジストリのデータベースへのアクセス方法Roskomnadzorは、「海賊版」映画のあるサイトのレジストリの導入を発表しました正規表現を学習、作成、およびテストするためのRegExr直感的なツール