回答編集履歴

3

一部、表現を修正

2019/11/11 17:57

投稿

dodox86
dodox86

スコア9183

test CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
 
24
24
 
25
- 0. 作成した自己(オレオレ)証明書の*.pfxファイルをWindows証明書マネージャでインポート
25
+ 0. 作成した自己証明書の*.pfxファイルをWindows証明書マネージャでインポート
26
26
 
27
27
  0. インポートしたWindows証明書マネージャで証明書のサムプリント(拇印)を取得
28
28
 
@@ -38,9 +38,9 @@
38
38
 
39
39
 
40
40
 
41
- ### 1. 作成した自己(オレオレ)証明書の*.pfxファイルをWindows証明書マネージャでインポート
42
-
43
- 質問者さんの「試したこと1」で、netsh コマンドによるSSL証明書のポート構成のバインド操作ですが、PowerShellのGet-PfxCertificateによる拇印ではダメでした。(私自身がこの辺りに不慣れなこともあって)様々なオプションを試しましたが、結局、以下の記事を参考にさせていただき、MMCでの「Windows証明書マネージャcertlm」を用いて証明書ファイルServerCert1.pfxをインポートしました。(すべてデフォルトの指定に沿います)
41
+ ### 1. 作成した自己証明書の*.pfxファイルをWindows証明書マネージャでインポート
42
+
43
+ 質問者さんの「試したこと1」で、`netsh` コマンドによるSSL証明書のポート構成のバインド操作ですが、PowerShellの`Get-PfxCertificate`コマンドで得た拇印ではダメでした。(私自身がこの辺りに不慣れなこともあって)様々なオプションを試しましたが、結局、以下の記事を参考にさせていただき、MMCでの「Windows証明書マネージャcertlm」を用いて自己(オレオレ)SSL証明書ファイルServerCert1.pfxをインポートしました。(すべてデフォルトの指定に沿います)
44
44
 
45
45
  [OnTimeサーバーにSSL証明書を設定する - OnTime Group Calendar](https://www3.ontimesuite.jp/ssl-cert/)
46
46
 

2

分かりづらい部分を修正

2019/11/11 17:57

投稿

dodox86
dodox86

スコア9183

test CHANGED
@@ -40,20 +40,20 @@
40
40
 
41
41
  ### 1. 作成した自己(オレオレ)証明書の*.pfxファイルをWindows証明書マネージャでインポート
42
42
 
43
+ 質問者さんの「試したこと1」で、netsh コマンドによるSSL証明書のポート構成のバインド操作ですが、PowerShellのGet-PfxCertificateによる拇印ではダメでした。(私自身がこの辺りに不慣れなこともあって)様々なオプションを試しましたが、結局、以下の記事を参考にさせていただき、MMCでの「Windows証明書マネージャcertlm」を用いて証明書ファイルServerCert1.pfxをインポートしました。(すべてデフォルトの指定に沿います)
44
+
45
+ [OnTimeサーバーにSSL証明書を設定する - OnTime Group Calendar](https://www3.ontimesuite.jp/ssl-cert/)
46
+
47
+
48
+
43
49
  ### 2. インポートしたWindows証明書マネージャで証明書のサムプリント(拇印)を取得
44
50
 
45
- 質問者さんの「試したこと1」で、netsh コマンドによるSSL証明書のポート構成のバインド操作ですが、PowerShellの`Get-PfxCertificate`による拇印ではダメでした。(私自身がこの辺りに不慣れなこともあって)様々なオプションを試しましたが、結局、以下の記事を参考にさせていただき、MMCでの「Windows証明書マネージャ`certlm`」を用いて証明書ファイルServerCert1.pfxをインポートしました。(すべてデフォルトの指定に沿います)証明書のサムプリント(拇印)は、のWindows証明書マネージャで得られたものを利用しました。
46
-
47
-
48
-
49
- [OnTimeサーバーにSSL証明書を設定する - OnTime Group Calendar](https://www3.ontimesuite.jp/ssl-cert/)
51
+ 証明書のサムプリント(拇印)は、1.のWindows証明書マネージャで得られたものを利用しました。 (操作方法は記事中に記載されています
50
52
 
51
53
 
52
54
 
53
55
  ### 3. `netsh`コマンドでポート構成をバインド
54
56
 
55
-
56
-
57
57
  証明書のサムプリントの取得部分が違うだけで、あとは質問者さんで行った方法と同じです。
58
58
 
59
59
  ```CMD

1

検証結果を追記

2019/11/11 17:48

投稿

dodox86
dodox86

スコア9183

test CHANGED
@@ -7,3 +7,459 @@
7
7
 
8
8
 
9
9
  開発環境上では同一PCということなので、hostsファイルなどを利用してホスト名の部分を合わせてみるか、IPアドレスを合わせてアクセスしてみてください。あるいは簡単に、クライアント側から "https://localhost:5000/TestService" でアクセスできるのであれば、やはりそういうことなのではないかな、と思います。
10
+
11
+
12
+
13
+ ---
14
+
15
+ **追記しました:2019-11-12 02:42**
16
+
17
+
18
+
19
+ 先の回答は外していました。くやしかった(?)のと、お手を煩わせてしまった罪滅ぼしに当方でも検証してみました。
20
+
21
+ 結果から書きますと、以下の処置で限定的ながら通信できるようになりました。
22
+
23
+
24
+
25
+ 0. 作成した自己(オレオレ)証明書の*.pfxファイルをWindows証明書マネージャでインポート
26
+
27
+ 0. インポートしたWindows証明書マネージャで証明書のサムプリント(拇印)を取得
28
+
29
+ 0. `netsh`コマンドでポート構成をバインド
30
+
31
+ 0. サーバー側プログラムで、匿名アクセスを受け付けるよう修正
32
+
33
+ 0. クライアント側プログラムで、「自己証明書による不正な証明書エラー」によるエラーを回避するよう修正
34
+
35
+
36
+
37
+ 以下、順にご説明します。
38
+
39
+
40
+
41
+ ### 1. 作成した自己(オレオレ)証明書の*.pfxファイルをWindows証明書マネージャでインポート
42
+
43
+ ### 2. インポートしたWindows証明書マネージャで証明書のサムプリント(拇印)を取得
44
+
45
+ 質問者さんの「試したこと1」で、netsh コマンドによるSSL証明書のポート構成のバインド操作ですが、PowerShellの`Get-PfxCertificate`による拇印ではダメでした。(私自身がこの辺りに不慣れなこともあって)様々なオプションを試しましたが、結局、以下の記事を参考にさせていただき、MMCでの「Windows証明書マネージャ`certlm`」を用いて証明書ファイルServerCert1.pfxをインポートしました。(すべてデフォルトの指定に沿います)証明書のサムプリント(拇印)は、このWindows証明書マネージャで得られたものを利用しました。
46
+
47
+
48
+
49
+ [OnTimeサーバーにSSL証明書を設定する - OnTime Group Calendar](https://www3.ontimesuite.jp/ssl-cert/)
50
+
51
+
52
+
53
+ ### 3. `netsh`コマンドでポート構成をバインド
54
+
55
+
56
+
57
+ 証明書のサムプリントの取得部分が違うだけで、あとは質問者さんで行った方法と同じです。
58
+
59
+ ```CMD
60
+
61
+ netsh http add sslcert ipport=0.0.0.0:5000 certhash=eae70a1d0144a9a367b4aa810f22b8e95815b602 appid={90164bb5-886c-4536-a752-7fbbf652c070} clientcertnegotiation=enable
62
+
63
+ ```
64
+
65
+
66
+
67
+ `netsh http show sslcert`でSSL証明書のバインド状況を確認すると、以下のようなものとなりました。
68
+
69
+ ```CMD
70
+
71
+ C> netsh http show sslcert
72
+
73
+ SSL 証明書のバインド:
74
+
75
+ -------------------------
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+ IP:ポート : 0.0.0.0:5000
84
+
85
+ 証明書ハッシュ : eae70a1d0144a9a367b4aa810f22b8e95815b602
86
+
87
+ アプリケーション ID : {90164bb5-886c-4536-a752-7fbbf652c070}
88
+
89
+ 証明書ストア名 : (null)
90
+
91
+ クライアント証明書の失効状態の検証: Enabled
92
+
93
+ キャッシュされたクライアント証明書のみを使用した失効状態の検証: Disabled
94
+
95
+ 使用法のチェック : Enabled
96
+
97
+ 失効リストの更新を確認する間隔: 0
98
+
99
+ URL 取得のタイムアウト : 0
100
+
101
+ Ctl 識別子 : (null)
102
+
103
+ Ctl ストア名 : (null)
104
+
105
+ DS マッパーの使用法 : Disabled
106
+
107
+ クライアント証明書のネゴシエート: Enabled
108
+
109
+ 接続の拒否 : Disabled
110
+
111
+ HTTP2 を無効にする : Not Set
112
+
113
+ QUIC を無効にする : Not Set
114
+
115
+ TLS1.2 を無効にする : Not Set
116
+
117
+ TLS1.3 を無効にする : Not Set
118
+
119
+ OCSP Stapling を無効にする : Not Set
120
+
121
+ トークンのバインドを有効にする : Not Set
122
+
123
+ 拡張イベントをログに記録する : Not Set
124
+
125
+ レガシ TLS バージョンを無効にする : Not Set
126
+
127
+ セッション チケットを有効にする : Not Set
128
+
129
+ 拡張プロパティ:
130
+
131
+ PropertyId : 0
132
+
133
+ 受信ウィンドウ : 1048576
134
+
135
+ 拡張プロパティ:
136
+
137
+ PropertyId : 1
138
+
139
+ フレームごとの最大設定 : 2796202
140
+
141
+ 1 分間の最大設定 : 4294967295
142
+
143
+ ```
144
+
145
+ ### 4. クライアント側プログラムで、「自己証明書による不正な証明書エラー」によるエラーを回避するよう修正
146
+
147
+
148
+
149
+ もとのサーバー、クライアントプログラムですと、自己証明書を使っていることによる、`System.ServiceModel.Security.SecurityNegotiationException` 「リモート証明書は無効です。」例外が起きます。
150
+
151
+ ```
152
+
153
+ System.ServiceModel.Security.SecurityNegotiationException
154
+
155
+ HResult=0x80131501
156
+
157
+ Message=機関 'servercn1:5000' との SSL/TLS のセキュリティで保護されているチャネルに対する信頼関係を確立できませんでした。
158
+
159
+ Source=mscorlib
160
+
161
+ スタック トレース:
162
+
163
+ ...(省略)
164
+
165
+
166
+
167
+ 内部例外 1:
168
+
169
+ WebException: 接続が切断されました: SSL/TLS のセキュリティで保護されているチャネルに対する信頼関係を確立できませんでした。
170
+
171
+
172
+
173
+ 内部例外 2:
174
+
175
+ AuthenticationException: 検証プロシージャによると、リモート証明書は無効です。
176
+
177
+ ```
178
+
179
+
180
+
181
+ これを避けるために、クライアント側に自己証明書であった場合でも、無理やりOKとするよう修正します。
182
+
183
+ 参考:[How to accept a self-signed SSL certificate in a WCF client? - Stack Overflow](https://stackoverflow.com/questions/4977218/how-to-accept-a-self-signed-ssl-certificate-in-a-wcf-client)
184
+
185
+
186
+
187
+ ```C#
188
+
189
+ // MessageData rtn = channel.PostMsg(msg); で送信する前に、リモート証明書の妥当性チェックコールバックを登録
190
+
191
+ ServicePointManager.ServerCertificateValidationCallback +=
192
+
193
+ new System.Net.Security.RemoteCertificateValidationCallback(EasyCertCheck);
194
+
195
+
196
+
197
+ // コールバックメソッド
198
+
199
+ bool EasyCertCheck(object sender, X509Certificate cert,
200
+
201
+ X509Chain chain, System.Net.Security.SslPolicyErrors error)
202
+
203
+ {
204
+
205
+ // 自己証明書の場合でも必ずチェックOKとする
206
+
207
+ Debug.WriteLine("EasyCertCheck");
208
+
209
+ return true;
210
+
211
+ }
212
+
213
+ ```
214
+
215
+ ### 5. サーバー側プログラムで、匿名アクセスを受け付けるよう修正
216
+
217
+
218
+
219
+ サーバー側のコードで、`binding.Security.Transport.ClientCredentialType`が`HttpClientCredentialType.Certificate`であると、以下の例外となります。HTTPステータス403なので一応は繋がっているかたちですが、成功としてレスポンスを受信したいので、この設定値を緩やかなものに変えます。
220
+
221
+ ```
222
+
223
+ System.ServiceModel.Security.MessageSecurityException
224
+
225
+ HResult=0x80131501
226
+
227
+ Message=この HTTP 要求は、クライアントの認証方式 'Anonymous' で許可されませんでした。
228
+
229
+ Source=WindowsFormsApp1
230
+
231
+ スタック トレース:
232
+
233
+ ...(省略)
234
+
235
+
236
+
237
+ 内部例外 1:
238
+
239
+ WebException: リモート サーバーがエラーを返しました: (403) 使用不可能
240
+
241
+ ```
242
+
243
+
244
+
245
+ ```C#
246
+
247
+ //ここを無効にして binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
248
+
249
+
250
+
251
+ // 匿名アクセスを可能とする
252
+
253
+ binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
254
+
255
+ ```
256
+
257
+
258
+
259
+ ### 6. まとめ
260
+
261
+ 自己証明書用でも構わず処理するようにクライアントを修正したのと、特に匿名アクセスでも受け付けるようにサーバーを修正した点は気になるところですが、一応https接続はできるようになったので、現状の回答として追記させてもらった次第です。
262
+
263
+
264
+
265
+ 検証した環境は以下となります。。
266
+
267
+ - Windows 10 Professional Version 1903 (OSビルド 18362.418)
268
+
269
+ - Visual Studio 2017 (Version 15.9.17)
270
+
271
+ - .NET Framework 4.5
272
+
273
+
274
+
275
+ プログラムの実行状況です。
276
+
277
+ ![プログラム実行状況](2bf0fad0b793d3ac094fbd74a2fc5b52.png)
278
+
279
+
280
+
281
+ クライアント側はProgram.csの修正量が多いので、全部掲載します。
282
+
283
+ ```C#
284
+
285
+ using System;
286
+
287
+ using System.Windows.Forms;
288
+
289
+ using System.Security.Cryptography.X509Certificates;
290
+
291
+ using System.ServiceModel;
292
+
293
+ using System.ServiceModel.Description;
294
+
295
+ using System.ServiceModel.Security;
296
+
297
+ using System.ServiceModel.Web;
298
+
299
+ using System.Net;
300
+
301
+ using System.Diagnostics;
302
+
303
+ using TestService;
304
+
305
+
306
+
307
+ namespace TestClient
308
+
309
+ {
310
+
311
+ public partial class Form1 : Form
312
+
313
+ {
314
+
315
+ WebChannelFactory<ITestService> cf = null;
316
+
317
+ ITestService channel = null;
318
+
319
+ //private static string pfxPath = @"D:\Work\TestService\ServerCert1.pfx";
320
+
321
+ private static string pfxPath = @"C:\project\teratail\221557\ServerCert1.pfx";
322
+
323
+ //private static string uris = @"https://123.123.123.123:5000/TestService";
324
+
325
+ //private static string uris = @"https://localhost:5000/TestService";
326
+
327
+ //private static string uris = @"https://ServerCN1:5000/TestService";
328
+
329
+ private static string uris = @"https://192.168.11.103:5000/TestService";
330
+
331
+
332
+
333
+ public Form1()
334
+
335
+ {
336
+
337
+ InitializeComponent();
338
+
339
+ }
340
+
341
+
342
+
343
+ private void Form1_Load(object sender, EventArgs e)
344
+
345
+ {
346
+
347
+ listBox1.HorizontalScrollbar = true;
348
+
349
+
350
+
351
+ //Uri uri = new Uri("https://123.123.123.123:5000/TestService");
352
+
353
+ Uri uri = new Uri(uris);
354
+
355
+ EndpointAddress endpointAddress = new EndpointAddress(uri);
356
+
357
+
358
+
359
+ //--------------------------チャンネル
360
+
361
+ cf = new WebChannelFactory<ITestService>(uri);
362
+
363
+ WebHttpBinding binding = cf.Endpoint.Binding as WebHttpBinding;
364
+
365
+ binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
366
+
367
+ binding.Security.Mode = WebHttpSecurityMode.Transport;
368
+
369
+
370
+
371
+ var behavior = new WebHttpBehavior();
372
+
373
+ behavior.FaultExceptionEnabled = false;
374
+
375
+ behavior.HelpEnabled = true;
376
+
377
+ behavior.DefaultOutgoingRequestFormat = WebMessageFormat.Json;
378
+
379
+ behavior.DefaultOutgoingResponseFormat = WebMessageFormat.Json;
380
+
381
+ cf.Endpoint.Behaviors.Add(behavior);
382
+
383
+
384
+
385
+ ServicePointManager.ServerCertificateValidationCallback +=
386
+
387
+ new System.Net.Security.RemoteCertificateValidationCallback(EasyCertCheck);
388
+
389
+
390
+
391
+ //var clientCertificate = new X509Certificate2(@"D:\Work\TestService\ServerCert1.pfx", "pswd", X509KeyStorageFlags.UserKeySet);
392
+
393
+ var clientCertificate = new X509Certificate2(pfxPath, "pswd", X509KeyStorageFlags.UserKeySet);
394
+
395
+ cf.Credentials.ClientCertificate.Certificate = clientCertificate;
396
+
397
+ cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
398
+
399
+ //cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust;
400
+
401
+
402
+
403
+ channel = cf.CreateChannel();
404
+
405
+ }
406
+
407
+
408
+
409
+ private void button1_Click(object sender, EventArgs e)
410
+
411
+ {
412
+
413
+ MessageData msg = new MessageData()
414
+
415
+ {
416
+
417
+ Name = "Taro",
418
+
419
+ Gender = 1,
420
+
421
+ Age = 3
422
+
423
+ };
424
+
425
+ try
426
+
427
+ {
428
+
429
+ MessageData rtn = channel.PostMsg(msg); //<--------ここでエラー発生
430
+
431
+ listBox1.Items.Insert(0, string.Format("Name:{0}, Gender:{1}, Age{2} ", rtn.Name, rtn.Gender, rtn.Age));
432
+
433
+ }
434
+
435
+ catch (Exception ex)
436
+
437
+ {
438
+
439
+ Trace.WriteLine(ex.Message);
440
+
441
+ throw ex;
442
+
443
+ }
444
+
445
+ }
446
+
447
+
448
+
449
+ private bool EasyCertCheck(object sender, X509Certificate cert,
450
+
451
+ X509Chain chain, System.Net.Security.SslPolicyErrors error)
452
+
453
+ {
454
+
455
+ Debug.WriteLine("EasyCertCheck");
456
+
457
+ return true;
458
+
459
+ }
460
+
461
+ }
462
+
463
+ }
464
+
465
+ ```