

### 前提

現在以下の構成で TCP サーバアプリケーションを作成しています。

[code]

    PC(クライアント)＜──インターネット──＞ロードバランサ ───────サーバ１
                            │─────────────────────────────サーバ２
                            │─────────────────────────────サーバ３
    
[/code]

サーバアプリケーションとしては .NET Framework の `Socket` クラスを使用しています。

ソケットクラスに指定しているパラメタとしては

  * `AddressFamily＃InterNetwork`
  * `SocketType＃Stream`
  * `ProtocolType＃Tcp`

インスタンス生成時、上記を設定（ TCP 送受信設定）しています。

また、環境は以下です。

  * クライアント PC：Windows 7
  * サーバ：Windowws Server2012
  * ロードバランサ：BIG-IP
  * 開発言語：C++/CLI
  * 実行環境：.NET Framework 4.5
  * プログラム作成環境：Visual Studio Pro 2012

## 質問事項

以下のコードで、本来は接続されたクライアントのIPアドレスを取得出来る想定でしたが、ロードバランサのIPアドレスが取得されます。

以下擬似コード

[code]

    Socket ClientSocket = ServerSocket.EndAccept(iAsyncResult);
    String IpAddress = ((IPEndPoint)ClientSocket.RemoteEndPoint).Address.ToString();
    Console.WriteLine(IpAddress);
    
    --------------
    出力結果：ロードバランサのIPアドレス
    --------------
    
[/code]

WireShark を使用してパケットモニタリングし、調査した結果、 IP ヘッダにはクライアント PC
のIPアドレスが入っていることがわかりました。おそらく、プログラムで取得するやり方が悪いのだと思われるのですが、 IP ヘッダに記載されている IP
アドレスを取得する方法がわかりません。

少しでも良いのでヒントになる情報があれば、ご教授くださると助かります。


CC BY-SA 3.0
2015-01-28T02:32:50.143
5477
2015-04-15T15:11:06.603
2015-01-28T03:37:13.760
4978
2647
question
windows .net socket
.NET　でロードバランサがある場合の送信元IPアドレス取得方法


考えられるのは

  1. .NETのバグ
  2. プログラムのバグ
  3. クライアントのアドレスがNATされている
  4. 実際にロードバランサとサーバが通信している

と言うところでしょうか(順不同)。

英語版にも同様の質問がありましたが、proxyじゃないのか、という回答がついてます。

[Socket.RemoteEndPoint returns gateway
address](https://stackoverflow.com/questions/18222140/socket-remoteendpoint-
returns-gateway-address)

コメントと重複するところもありますが、一般論として確認する項目や方法を列挙しておきます。

## トレース情報の出力

[トレース情報の出力を有効](https://msdn.microsoft.com/ja-
jp/library/ty48b824%28v=vs.110%29.aspx)にすることで、Socketのトレースがとれます。

[code]

    System.Net.Sockets Information: 0 : [4292] Socket#45653674 - 192.168.1.2:58849 から 192.168.1.1:22222 への接続を受け入れました。
    
[/code]

## netstat

[code]

    C:\> netstat -n
      アクティブな接続
    
      プロトコル  ローカル アドレス          外部アドレス        状態
      TCP    127.0.0.1:22222        127.0.0.1:51819        ESTABLISHED
      TCP    192.168.1.1:22222      192.168.1.2:58849      ESTABLISHED
    
[/code]

不要分を省略してますが、この例だとサーバのポート(22222)に対して2つの接続があります。

クライアント-サーバの接続が正しく表示されていますか？また、ロードバランサ-サーバの接続がありませんか？

## パケットダンプ

[Wireshark](https://www.wireshark.org/)等のネットワークアナライザでパケットを取得し確認する。

このとき注意することとしては、「自分の意図どおりのパケット」以外にも注目することです。

今回の例では、PC-
サーバ宛てのパケットが「意図通りのパケット」に当たりますが、実はそのパケットではコネクションが張れていないとか、それ以外にロードバランサ-
サーバ間の通信が実際に存在したりしませんか。

## ロードバランサ

ロードバランサは(設計)設定によってクライアントだったりサーバだったりのアドレスを変換します。どのような設定になっているか確認してください。

また、ヘルスチェックを行っている場合、ロードバランサがサーバに接続します。これが意図しない不具合を起こす場合もあります。(ソケットが埋まるなど)


CC BY-SA 3.0
2015-02-04T02:09:57.767
5907
2015-02-04T02:09:57.767
2017-05-23T12:38:56.083
-1
5793
5477
answer


WebRequestではなくSocketを使っていることから、HTTP以外のプロトコルかな？という気もしますが、仮にHTTPであれば、BIG-
IPがアドレスを付け替えた際に、HTTPヘッダにX-Forwarded-Forヘッダを付けます。

<http://ja.wikipedia.org/wiki/X-Forwarded-For>

で、HTTPヘッダに情報が乗っていればWebRequest.Headersプロパティから取得できると思います。（試してませんが・・・）


CC BY-SA 3.0
2015-02-14T14:13:56.197
6488
2015-02-14T14:13:56.197
8278
5477
answer