ルーターのパブリックIPの検索に関する情報を取得または検索できないようです。これは、この方法で行うことができず、Webサイトから取得する必要があるためですか?
C#を使用して、webclientは短いものです。
public static void Main(string[] args)
{
string externalip = new WebClient().DownloadString("http://icanhazip.com");
Console.WriteLine(externalip);
}
コマンドライン(LinuxとWindowsの両方で動作)
wget -qO- http://bot.whatismyipaddress.com
OR
curl http://ipinfo.io/ip
static void Main(string[] args)
{
HTTPGet req = new HTTPGet();
req.Request("http://checkip.dyndns.org");
string[] a = req.ResponseBody.Split(':');
string a2 = a[1].Substring(1);
string[] a3=a2.Split('<');
string a4 = a3[0];
Console.WriteLine(a4);
Console.ReadLine();
}
IP DNSの確認 でこの小さなトリックを実行します
Goldb-Httpget C# にあるHTTPGet
クラスを使用します
.Net WebRequestの場合:
public static string GetPublicIP()
{
string url = "http://checkip.dyndns.org";
System.Net.WebRequest req = System.Net.WebRequest.Create(url);
System.Net.WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
string response = sr.ReadToEnd().Trim();
string[] a = response.Split(':');
string a2 = a[1].Substring(1);
string[] a3 = a2.Split('<');
string a4 = a3[0];
return a4;
}
string pubIp = new System.Net.WebClient().DownloadString("https://api.ipify.org");
同様の優れたサービスを使用する
private string GetPublicIpAddress()
{
var request = (HttpWebRequest)WebRequest.Create("http://ifconfig.me");
request.UserAgent = "curl"; // this will tell the server to return the information as if the request was made by the linux "curl" command
string publicIPAddress;
request.Method = "GET";
using (WebResponse response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
publicIPAddress = reader.ReadToEnd();
}
}
return publicIPAddress.Replace("\n", "");
}
理論的には、ルーターはネットワークのパブリックIPアドレスを通知できるはずですが、これを行う方法は、一部のルーターデバイスでも可能であれば、一貫性のない/非直線的なものになります。
最も簡単でありながら非常に信頼性の高い方法は、Webサーバーが認識するIPアドレスを返すWebページにリクエストを送信することです。 Dyndns.orgはこのための優れたサービスを提供します。
返されるのは、テキストCurrent IP Address: 157.221.82.39
(偽のIP)。HTTP応答から簡単に抽出できます。
これを拡張 answer by @ suneel ranga :
static System.Net.IPAddress GetPublicIp(string serviceUrl = "https://ipinfo.io/ip")
{
return System.Net.IPAddress.Parse(new System.Net.WebClient().DownloadString(serviceUrl));
}
System.Net.WebClient
でサービスを使用する場合は、単にIPアドレスを文字列として表示し、 System.Net.IPAddress
オブジェクトを使用します。以下にそのようなサービスをいくつか示します*:
*一部のサービスは、この質問とこれらから言及されました スーパーユーザーサイトからの回答 。
http://checkip.dyndns.org/ は処理しなければならないhtmlタグを与えていましたが、 https://icanhazip.com/ は単に私に単純な文字列。残念ながら https://icanhazip.com/ はip6アドレスを教えてくれ、ip4が必要でした。幸いなことに、ipv4.icanhazip.comとipv6.icanhazip.comから選択できる2つのサブドメインがあります。
string externalip = new WebClient().DownloadString("https://ipv4.icanhazip.com/");
Console.WriteLine(externalip);
Console.WriteLine(externalip.TrimEnd());
数行のコードで、このための独自のHttpサーバーを作成できます。
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+/PublicIP/");
listener.Start();
while (true)
{
HttpListenerContext context = listener.GetContext();
string clientIP = context.Request.RemoteEndPoint.Address.ToString();
using (Stream response = context.Response.OutputStream)
using (StreamWriter writer = new StreamWriter(response))
writer.Write(clientIP);
context.Response.Close();
}
その後、パブリックIPを知る必要があるときはいつでも、これを行うことができます。
WebClient client = new WebClient();
string ip = client.DownloadString("http://serverIp/PublicIP");
接続なしで外部IPを取得するための高速な方法実際にはそのためのHTTP接続は必要ありません
最初に、参照にNATUPNPLib.dllを追加し、参照から選択し、プロパティウィンドウから相互運用機能タイプをFalseにチェックする必要があります。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NATUPNPLib; // Add this dll from referance and chande Embed Interop Interop to false from properties panel on visual studio
using System.Net;
namespace Client
{
class NATTRAVERSAL
{
//This is code for get external ip
private void NAT_TRAVERSAL_ACT()
{
UPnPNATClass uPnP = new UPnPNATClass();
IStaticPortMappingCollection map = uPnP.StaticPortMappingCollection;
foreach (IStaticPortMapping item in map)
{
Debug.Print(item.ExternalIPAddress); //This line will give you external ip as string
break;
}
}
}
}
checkip.dyndns.orgは常に正しく機能するとは限りません。たとえば、私のマシンの場合、NAT後の内部アドレスが表示されます。
Current IP Address: 192.168.1.120
NATの背後にローカルDNSゾーンがあり、ブラウザがそのローカルIPアドレスをcheckipに送信し、それが返されるため、これが起こっていると思います。
また、httpは重いテキスト指向のTCPベースのプロトコルであるため、外部IPアドレスの迅速かつ効率的な定期的な要求にはあまり適していません。特にこの目的のために設計されたUDPベースのバイナリSTUNを使用することをお勧めします。
http://en.wikipedia.org/wiki/STUN
STUN-serverは「UDPミラー」のようなものです。あなたはそれを見て、「私がどのように見えるか」を見る。
世界中に多くのパブリックSTUNサーバーがあり、外部IPをリクエストできます。たとえば、こちらをご覧ください。
http://www.voip-info.org/wiki/view/STUN
たとえば、インターネットからSTUNクライアントライブラリをダウンロードできます。
http://www.codeproject.com/Articles/18492/STUN-Client
そしてそれを使用します。
System.Net.Http
のHttpClient
を使用して実行します。
public static string PublicIPAddress()
{
string uri = "http://checkip.dyndns.org/";
string ip = String.Empty;
using (var client = new HttpClient())
{
var result = client.GetAsync(uri).Result.Content.ReadAsStringAsync().Result;
ip = result.Split(':')[1].Split('<')[0];
}
return ip;
}
基本的に、IPの1つにアクセスできない場合に備えて、追加のバックアップを使用することを好みます。そこで、この方法を使用します。
public static string GetExternalIPAddress()
{
string result = string.Empty;
try
{
using (var client = new WebClient())
{
client.Headers["User-Agent"] =
"Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) " +
"(compatible; MSIE 6.0; Windows NT 5.1; " +
".NET CLR 1.1.4322; .NET CLR 2.0.50727)";
try
{
byte[] arr = client.DownloadData("http://checkip.amazonaws.com/");
string response = System.Text.Encoding.UTF8.GetString(arr);
result = response.Trim();
}
catch (WebException)
{
}
}
}
catch
{
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://ipinfo.io/ip").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://api.ipify.org").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://icanhazip.com").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://wtfismyip.com/text").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("http://bot.whatismyipaddress.com/").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
string url = "http://checkip.dyndns.org";
System.Net.WebRequest req = System.Net.WebRequest.Create(url);
System.Net.WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
string response = sr.ReadToEnd().Trim();
string[] a = response.Split(':');
string a2 = a[1].Substring(1);
string[] a3 = a2.Split('<');
result = a3[0];
}
catch (Exception)
{
}
}
return result;
}
GUIコントロール(WPF、.NET 4.5)を更新するために、たとえばいくつかのラベルをこのコードを使用します
void GetPublicIPAddress()
{
Task.Factory.StartNew(() =>
{
var ipAddress = SystemHelper.GetExternalIPAddress();
Action bindData = () =>
{
if (!string.IsNullOrEmpty(ipAddress))
labelMainContent.Content = "IP External: " + ipAddress;
else
labelMainContent.Content = "IP External: ";
labelMainContent.Visibility = Visibility.Visible;
};
this.Dispatcher.InvokeAsync(bindData);
});
}
役に立てば幸いです。
ここ は、このコードを含むアプリの例です。
public static string GetPublicIP()
{
return new System.Net.WebClient().DownloadString("https://ipinfo.io/ip").Replace("\n","");
}
デバッグするとき、次を使用して外部呼び出し可能なURLを作成しますが、最初の2行を使用してパブリックIPを取得できます。
public static string ExternalAction(this UrlHelper helper, string actionName, string controllerName = null, RouteValueDictionary routeValues = null, string protocol = null)
{
#if DEBUG
var client = new HttpClient();
var ipAddress = client.GetStringAsync("http://ipecho.net/plain").Result;
// above 2 lines should do it..
var route = UrlHelper.GenerateUrl(null, actionName, controllerName, routeValues, helper.RouteCollection, helper.RequestContext, true);
if (route == null)
{
return route;
}
if (string.IsNullOrEmpty(protocol) && string.IsNullOrEmpty(ipAddress))
{
return route;
}
var url = HttpContext.Current.Request.Url;
protocol = !string.IsNullOrWhiteSpace(protocol) ? protocol : Uri.UriSchemeHttp;
return string.Concat(protocol, Uri.SchemeDelimiter, ipAddress, route);
#else
helper.Action(action, null, null, HttpContext.Current.Request.Url.Scheme)
#endif
}
プログラマの回答の@Academyを短いコードにリファクタリングし、https://
URLのみにヒットするように変更しました。
public static string GetExternalIPAddress()
{
string result = string.Empty;
string[] checkIPUrl =
{
"https://ipinfo.io/ip",
"https://checkip.amazonaws.com/",
"https://api.ipify.org",
"https://icanhazip.com",
"https://wtfismyip.com/text"
};
using (var client = new WebClient())
{
client.Headers["User-Agent"] = "Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) " +
"(compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
foreach (var url in checkIPUrl)
{
try
{
result = client.DownloadString(url);
}
catch
{
}
if (!string.IsNullOrEmpty(result))
break;
}
}
return result.Replace("\n", "").Trim();
}
}
外部Webサービスの使用に基づく回答は、実際には記載されている質問に答えていないため、正確ではありません。
...検出に関する情報my routerspublic IP
説明
すべてのオンラインサービスは外部IPアドレスを返しますが、本質的にこのアドレスがユーザーのルーターに割り当てられることを意味するわけではありません。
ルーターには、ISPインフラストラクチャネットワークの別のローカルIPアドレスが割り当てられる場合があります。実際には、これは、ルーターがインターネット上で利用可能なサービスをホストできないことを意味します。これは、ほとんどのホームユーザーの安全には適していますが、自宅のサーバーをホストするオタクには適していません。
ルーターに外部IPがあるかどうかを確認する方法は次のとおりです。
Wikipedia の記事によると、IPアドレス範囲10.0.0.0 – 10.255.255.255
、172.16.0.0 – 172.31.255.255
、および192.168.0.0 – 192.168.255.255
は、プライベート、つまりローカルネットワークに使用されます。
ルーターに外部IPアドレスが割り当てられているリモートホストへのルートをトレースするとどうなるかを確認します。
ガッチャ!最初のホップは31.*
から始まります。これは明らかに、ルーターとインターネットの間に何もないことを意味します。
解決
Ttl = 2
を使用して特定のアドレスにPingしますTTL = 2は、リモートホストに到達するには不十分である必要があります。ホップ#1ホストは"Reply from <ip address>: TTL expired in transit."
を発行し、IPアドレスを公開します。
実装
try
{
using (var ping = new Ping())
{
var pingResult = ping.Send("google.com");
if (pingResult?.Status == IPStatus.Success)
{
pingResult = ping.Send(pingResult.Address, 3000, "ping".ToAsciiBytes(), new PingOptions { Ttl = 2 });
var isRealIp = !Helpers.IsLocalIp(pingResult?.Address);
Console.WriteLine(pingResult?.Address == null
? $"Has {(isRealIp ? string.Empty : "no ")}real IP, status: {pingResult?.Status}"
: $"Has {(isRealIp ? string.Empty : "no ")}real IP, response from: {pingResult.Address}, status: {pingResult.Status}");
Console.WriteLine($"ISP assigned REAL EXTERNAL IP to your router, response from: {pingResult?.Address}, status: {pingResult?.Status}");
}
else
{
Console.WriteLine($"Your router appears to be behind ISP networks, response from: {pingResult?.Address}, status: {pingResult?.Status}");
}
}
}
catch (Exception exc)
{
Console.WriteLine("Failed to resolve external ip address by ping");
}
小さなヘルパーは、IPがプライベートネットワークまたはパブリックネットワークに属しているかどうかを確認するために使用されます。
public static bool IsLocalIp(IPAddress ip) {
var ipParts = ip.ToString().Split(new [] { "." }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
return (ipParts[0] == 192 && ipParts[1] == 168)
|| (ipParts[0] == 172 && ipParts[1] >= 16 && ipParts[1] <= 31)
|| ipParts[0] == 10;
}
答えのほとんどは、ソリューションで http://checkip.dyndns.org に言及しています。私たちにとってはうまくいきませんでした。私たちは多くの時間をタイムムートに直面しました。プログラムがIP検出に依存している場合、それは本当に厄介です。
ソリューションとして、デスクトップアプリケーションの1つで次の方法を使用します。
// Returns external/public ip
protected string GetExternalIP()
{
try
{
using (MyWebClient client = new MyWebClient())
{
client.Headers["User-Agent"] =
"Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) " +
"(compatible; MSIE 6.0; Windows NT 5.1; " +
".NET CLR 1.1.4322; .NET CLR 2.0.50727)";
try
{
byte[] arr = client.DownloadData("http://checkip.amazonaws.com/");
string response = System.Text.Encoding.UTF8.GetString(arr);
return response.Trim();
}
catch (WebException ex)
{
// Reproduce timeout: http://checkip.amazonaws.com:81/
// trying with another site
try
{
byte[] arr = client.DownloadData("http://icanhazip.com/");
string response = System.Text.Encoding.UTF8.GetString(arr);
return response.Trim();
}
catch (WebException exc)
{ return "Undefined"; }
}
}
}
catch (Exception ex)
{
// TODO: Log trace
return "Undefined";
}
}
良い点は、両方のサイトがIPを単純な形式で返すことです。したがって、文字列操作は回避されます。
catch
句のロジックを確認するには、使用できないポートを押してタイムアウトを再現できます。例: http://checkip.amazonaws.com:81/
IPIFY API は、生のテキストとJSONで応答できるため、素晴らしいです。また、コールバックなどを行うこともできます。唯一の問題は、6ではなくIPv4で応答することです。
私が見つけたベストアンサー
リモートIPアドレスをできるだけ早く取得するため。ダウンローダーを使用するか、コンピューターにサーバーを作成する必要があります。
この単純なコードを使用することのマイナス面:(推奨)初期化されたWebClientはプロキシ設定の確認に常に3-5秒かかるため、リモートIPアドレスを取得するのに3-5秒かかるということです。
public static string GetIP()
{
string externalIP = "";
externalIP = new WebClient().DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
ここに私がそれを修正した方法があります。(初回はまだ3〜5秒かかります)が、その後は接続に応じて常に0〜2秒でリモートIPアドレスを取得します。
public static WebClient webclient = new WebClient();
public static string GetIP()
{
string externalIP = "";
externalIP = webclient.DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
public string GetClientIp() {
var ipAddress = string.Empty;
if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) {
ipAddress = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
} else if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_CLIENT_IP"] != null &&
System.Web.HttpContext.Current.Request.ServerVariables["HTTP_CLIENT_IP"].Length != 0) {
ipAddress = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_CLIENT_IP"];
} else if (System.Web.HttpContext.Current.Request.UserHostAddress.Length != 0) {
ipAddress = System.Web.HttpContext.Current.Request.UserHostName;
}
return ipAddress;
}
完璧に動作します
using System.Net;
private string GetWorldIP()
{
String url = "http://bot.whatismyipaddress.com/";
String result = null;
try
{
WebClient client = new WebClient();
result = client.DownloadString(url);
return result;
}
catch (Exception ex) { return "127.0.0.1"; }
}
ループバックをフォールバックとして使用して、物事が致命的に壊れないようにしました。
Telnet を使用して、WAN IP。
Telnetパート
Telnet部分は、たとえば、 this Minimalistic Telnet code をAPIとして使用して、Telnetコマンドをルーターに送信し、ルーターの応答を取得できます。この回答の残りの部分では、何らかの方法でTelnetコマンドを送信し、コードで応答を取得するように設定されていることを前提としています。
アプローチの制限
他のアプローチと比較してルーターを照会することの1つの欠点は、作成するコードがルーターモデルにかなり固有である可能性が高いことです。とはいえ、外部サーバーに依存しない便利なアプローチになる可能性があります。とにかく、独自のソフトウェアからルーターにアクセスして、設定や制御など、他の目的でルーターにアクセスし、特定のコードを書く価値を高めることができます。
ルーターコマンドと応答の例
以下の例はすべてのルーターに適しているわけではありませんが、原則的にアプローチを示しています。ルーターのコマンドと応答に合わせて詳細を変更する必要があります。
たとえば、ルーターにWAN IPを表示させる方法は、次のTelnetコマンドです。
connection list
出力は、接続ごとに1行のテキスト行のリストで構成され、IPアドレスはオフセット39になります。WAN接続の行は、この線:
RESP: 3947 17.110.226. 13:443 146.200.253. 16:60642 [R..A] Internet 6 tcp 128
<------------------ 39 -------------><-- WAN IP -->
出力では、各IPアドレスセグメントに3文字のスペースが埋め込まれる場合がありますが、削除する必要があります。 (つまり、上記の例では、「146.200.253。16」を「146.200.253.16」に変換する必要があります。)
ルーターの実験または参照資料を参照することにより、特定のルーターに使用するコマンドと、ルーターの応答を解釈する方法を確立できます。
WAN IPを取得するコード
(Telnetパーツ用のメソッドsendRouterCommand
があると仮定します。上記を参照してください。)
上記のルーターの例を使用して、次のコードはWAN IPを取得します。
private bool getWanIp(ref string wanIP)
{
string routerResponse = sendRouterCommand("connection list");
return (getWanIpFromRouterResponse(routerResponse, out wanIP));
}
private bool getWanIpFromRouterResponse(string routerResponse, out string ipResult)
{
ipResult = null;
string[] responseLines = routerResponse.Split(new char[] { '\n' });
// RESP: 3947 17.110.226. 13:443 146.200.253. 16:60642 [R..A] Internet 6 tcp 128
//<------------------ 39 -------------><--- 15 --->
const int offset = 39, length = 15;
foreach (string line in responseLines)
{
if (line.Length > (offset + length) && line.Contains("Internet"))
{
ipResult = line.Substring(39, 15).Replace(" ", "");
return true;
}
}
return false;
}