Kontakt für Domain-Missbrauch mit C# von abuse.net ermitteln
Der Anbieter stellt alle wesentlichen Informationen zur Umsetzung zur Verfügung. Dort wird der Zugriff per DNS oder Whois beschrieben. Das Herunterladen der (Roh-)Daten ist jedoch nicht möglich. Beachtet bitte außerdem die Nutzungsbedingungen, so ist der kommerzielle Einsatz beispielsweise nicht ohne Weiteres gestattet.
Es werden bei den folgenden beispielhaften Implementierungen lediglich die ermittelten eMail-Adressen an sich zurückgeliefert und keine – ebenfalls verfügbaren – Kommentare, welche insbesondere Angaben zur Quelle enthalten. Des Weiteren findet keine Reduzierung von Duplikaten statt. Beides kann bei Bedarf aber selbstverständlich noch angepasst bzw. ergänzt werden. Die Methoden sind darüber hinaus variadisch und können daher mit mehreren Argumenten (oder einem Feld) aufgerufen werden.
Zugriff per Whois
Eine – auch mit .NET-Bordmitteln – sehr einfache Möglichkeit der Abfrage des für Missbrauch zuständigen Kontakts zu einer Domain ist das Whois-Protokoll. Die Abfrage erfolgt per TCP bei whois.abuse.net:43
.
01020304050607080910111213141516171819202122
public static IEnumerable<string> GetAbuseContactList(params string[] domainList) { using(TcpClient client = new TcpClient("whois.abuse.net", 43)) { using(NetworkStream stream = client.GetStream()) { byte[] request = Encoding.UTF8.GetBytes(String.Join(" ", domainList) + "\r\n"); stream.Write(request, 0, request.Length);
using(StreamReader streamReader = new StreamReader(stream)) { while(!streamReader.EndOfStream) { string response = streamReader.ReadLine();
if(response.Contains("(")) { response = response.Substring(0, response.IndexOf('(')); }
if(!String.IsNullOrWhiteSpace(response)) { yield return response.Trim(); } } } } }}
Es sei jedoch darauf hingewiesen, dass diese Methode vom Anbieter nicht (mehr) empfohlen und möglicherweise eingestellt wird. Darüber hinaus ist das Abfragen im Vergleich zu DNS um den Faktor 2-3 langsamer.
Zugriff per DNS
Eine sehr effiziente Möglichkeit der Abfrage stellt das DNS durch Auflösung des Bezeichners {domain}.contacts.abuse.net
dar; die Rückgabe der Adressen erfolgt in Form von TXT-Records.
Leider stellt das .NET-Framework jedoch nur einfache Aufgaben der Adress- und Namensauflösung per DNS
-Klasse zur Verfügung. Da die Details der Kommunikation – zumindest in diesem Beitrag – nicht weiter vertieft werden sollen, greifen wir auf eine externe Laufzeitbibliothek zu, die wir mit NuGet bequem per Visual Studio beziehen können. Für das folgende Beispiel verwende ich ARSoft.Tools.Net
, welche sich bereits in einigen meiner Entwicklungen im Produktiveinsatz bewährt hat und zudem auch relativ einfach zu verwenden ist.
010203040506070809101112
public static IEnumerable<string> GetAbuseContactList(params string[] domainList) { foreach(string domain in domainList) { DnsMessage response = DnsClient.Default.Resolve( DomainName.Parse(domain + ".contacts.abuse.net"), RecordType.Txt );
foreach(TxtRecord record in response.AnswerRecords) { yield return record.TextData; } }}
0102030405060708
// ["abuse@coders-online.net"]IEnumerable<string> abuseContactList = GetAbuseContactList("coders-online.net");
// ["abuse@google.com", "abuse@microsoft.de"]abuseContactList = GetAbuseContactList("google.com", "microsoft.de");
// ["abuse@facebook.com", "spamreport@spamreport.facebook.com"]abuseContactList = GetAbuseContactList("facebook.com");
DNS-Cache unter Windows und mit C# leeren
ipconfig /flushdns
.Prinzipiell wäre es zwar möglich, das Programm
ipconfig
mit dem Argument /flushdns
über die Process
-Klasse per C# aufzurufen, jedoch ist dies nicht ganz unproblematisch, da die Ausführung längere Zeit dauern kann.Alternativ hilft uns hier – wieder einmal – die Windows-API in Kombination mit dem
DllImport
-Attribut:
01020304050607
public static class DnsUtility { [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")] public static extern void FlushCache();}
// DNS-Cache leerenDnsUtility.FlushCache();
Dns
-Klasse nützlich, um aktuelle Daten zu erhalten. Natürlich gibt es einen solchen Zwischenspeicher aber nicht grundlos, d. h. es ist nur äußerst selten ratsam, diesen immer wieder vor einer Namensauflösung zu leeren – Performanzdifferenzen im Rahmen einer Größenordnung sind hier üblich. Im Rahmen des Debuggings oder für besonders kritische Prozesse kann das Vorgehen jedoch durchaus sinnvoll sein. Bezeichner eines Members mit C# ermitteln
ArgumentException
und abgeleiteten Klassen), Logging (im Sinne von "Methode MethodName
betreten/verlassen") oder auch beim Routing im Rahmen des ASP.NET MVC-Frameworks in die Notwendigkeit, Programmbezeichner als Zeichenketten anzugeben.Etwas ärgerlich ist hier jedoch immer, was man bei grundsätzlich statisch typisierten Sprachen wie C# für gewöhnlich vermeiden möchte: Derartige Zeichenketten sind literal hinterlegt und dementsprechend einer Refaktorierung nicht ohne Weiteres zugänglich. Dieses Problem löst nun das relativ neue Konstrukt
nameof
, indem es die (einfachen) Bezeichner von Variablen, Typen und Membern als Zeichenkette liefert:
01020304050607080910111213141516171819202122
public class Person { public string FirstName { get; set; }
public string LastName { get; set; }
public void Marry(Person person) { /* … */ }}
Debug.WriteLine(nameof(Person)); // "Person"Debug.WriteLine(nameof(Person.FirstName)); // "FirstName"Debug.WriteLine(nameof(Person.LastName)); // "LastName"Debug.WriteLine(nameof(Person.Marry)); // "Marry"
nameof
auswirkt und somit für Konsistenz sorgt.Ein weiterer theoretischer Anwendungsfall ergibt sich im Rahmen einer
INotifyPropertyChanged
-Implementierung, jedoch lässt sich dieses Problem auch ganz ohne manuelle Angabe per CallerMemberName
-Attribut lösen, wie ich in einem früheren Beitrag bereits beschrieben habe. Anwendungssymbol mit C# extrahieren
*.exe
) enthalten häufig ein Programmsymbol, welches insbesondere im Windows Explorer und auf der Taskleiste angezeigt wird. Das Ermitteln dieses Anwendungssymbols, beispielsweise für eigene Auflistungen, ist sehr einfach über Icon.ExtractAssociatedIcon()
realisierbar:
0102030405060708091011
using(Icon icon = Icon.ExtractAssociatedIcon("devenv.exe")) { // Programmsymbol als *.ico-Datei speichern using(FileStream fileStream = File.OpenWrite("devenv.ico")) { icon.Save(fileStream); }
// Programmsymbol als *.png-Datei speichern using(Bitmap bitmap = icon.ToBitmap()) { bitmap.Save("devenv.png", ImageFormat.Png); }}
Feedreader
Mir bekannte Lösungen zur lokalen Anwendung sind dabei jedoch mitunter recht unpraktisch, da ich u. a. auch gerne – ohne umständliche Synchronisierung – von unterwegs darauf zugreifen möchte. Mir bekannte webbasierte Lösungen wiederum sind oftmals recht schwerfällig, überladen oder mit störender Werbung versehen. Es lag daher nahe, eine eigene Lösung zu schaffen, die möglichst kompakt, schnell und übersichtlich ist. Das System sollte den Fokus auf die eigentlichen Inhalte lenken und bei der Navigation ähnlich einem eMail-Client strukturiert sein.
Nach relativ kurzer Entwicklungszeit ist daraus ein kleines Feedreader-Projekt entstanden. Da ich gerne auf neue Inhalte verweise oder einen Podcast unterstützen möchte, dachte ich mir, dass darauf auch durchaus weitere Personen zugreifen können – wozu ihr hiermit eingeladen seid. Beachtet aber bitte, dass ihr dort wirklich nur meine persönliche Auswahl verfolgen könnt und derzeit keine eigenen Benutzerkonten angelegt oder sonstige Einstellungen getätigt werden können. Weitere Informationen findet ihr direkt auf der neuen Webseite.
Für die technisch interessierten Leser, zu denen wohl die meisten dieses Blogs gehören dürften, sei noch ergänzt, dass die Kernfunktionalität des Projekts auf der
SyndicationFeed
-Klasse des .NET-Frameworks basiert.Die Webpräsenz ist auf Deutsch, Englisch und Niederländisch verfügbar; die Einstellung wird vom Browser bezogen. Vorschläge zu weiteren Funktionen und Meldungen zu Fehlern werden jederzeit gerne per Tracker angenommen.
Project links
-
BitStadt – Stadtportal
Berlin · Hamburg · Amsterdam -
CCC – Fahrplan
Schedules for the CCCongress
Categories / Archive | Übersicht
- PHP functions in C# (136)
- Dictionary (257)