.NET Framework, internete bağlanan her şey için HTTP ve HTTPS proxy desteği verir. Ama ne yazık ki SOCKS5 proxy'ler ilgi alanı dışında kalmıştır.
E biz heçkırız, Tor kullanacağız yahu! Tor bir SOCKS5 proxy'dir, bizi nasıl engellerler?!
Hadi hemen bir Socks5 sınıfı oluşturalım. Ben tembellik yapıyorum aslında. DoS programımın zaten Socks5 portları üstünden aktarım yapma yeteneği var, yani bu class'ın elimde yapılmışı var
Bunu bir Dynamic Link Library, yani dll projesi olarak yapacağız ki diğer projelerimizde hızlıca aktarıverelim.
Class'ı oluşturduktan sonra bilmemiz gereken tek şeyler SOCKS5 proxy'nin adresi ve portu. Bunun için gerekli alanları ve constructor'ı yazalım...
Ne yaptık? Proxy adres ve portunu kaydettikten sonra sonradan kullanacağımız soketi de hazırlayıverdik. Ama daha hiç bir yere bağlanmadık! Kullanıcı "bağlan" desin öyle bağlanacağız. Yoksa gereksiz timeout'ları kontrol etmemiz gerekir. "baglanti" değerini sonradan kullanacağız. Şimdilik kafanıza takmayın.
Sonra yapacağımız ise sadece "bağlanmak". Bunu adım adım yapacağız.
İlk işimiz, "arkadaş socks versiyonun 5 olmalı, bir tane authentication metodu kabul ediyorum, o da 0, yani auth olmadan kullanmak" demek. Sırayla 5, 1 (1 tane auth türü) ve 0 göndermek yani..
Sadece soketimizi proxy'ye bağladık, sonra dediğim gibi sadece 5, 1 ve 0 byte'larını gönderdik. Şimdi sunucunun cevabını dinleyeceğiz, bu da sadece 2 byte olacak. Ama sonradan daha büyük buffer kullanacağımızdan baştan ben 50 byte'lık bir buffer açıyorum.
Sunucu cevap olarak önce protokolünü tekrar edecek, yani ilk byte 5 gönderecek. İkinci byte, auth olmadan girişi kabul etmişse bu protokol numarasının tekrarı olacak, yani 0, yok kabul etmemişse 255 olacak.
Bir buffer oluşturduk, o buffer'a okuma yaptık, yaptığımız okumanın 2. byte'ı 0 değilse "yanlış" döndürerek çıktık çünkü bağlanamıyoruz.
Sonra tekrar versiyon numarasını göndeririz tek byte, yani 5. İsteğimiz TCP ile porta bağlanmak ise 1, TCP portu bind etmek ise 2 (TOR bunu desteklemez, ücretsiz hiç bir proxy desteklemez) veya UDP bağlantı kurmak ise 3 göndeririz(TOR UDP'yi de desteklemez.)
Benim amacım TCP portuna bağlanmak şu anda, 1 göndereceğim. Bunun ardından tek bir byte 0 gönderiyoruz. Bu rezerve bir değer, hep göndermek zorundayız.
Sonra da adres gönderim şekli var. IP gönderiyorsak 1, domain adı gönderiyorsak 3, IPv6 gönderiyorsak 4 göndeririz.
Biz domain adresi göndermek istedik, kullanıcıdan string istedik.
Eğer IPv4 veya IPv6 gönderiyorsak bu IP'nin byte'larını sırayla gönderirdik. Ama domain adı her uzunlukta olabileceğinden ilk byte olarak uzunluğunu, ardından da bütün domain adresini gödneriyoruz.
En son da kullanacağımız portu, 2 byte olarak (0-65535 arası her port olabilir) gönderiyoruz bu kadar.
Yani ne diyoruz; öncelikle protokol, sonra bağlantı türü,sonra rezerve olan 0, sonra adres türü.
Sonra bunu domain adresinin boyutu ile birleştiriyoruz...
Sonra domain'in kendisini yazıyoruz ardına..
En son da port adresimizi yazalım. Little endian unsigned short olarak yazacağız. Yani önce portumuzun son byte'ını, sonra ilk byte'ını yazıyoruz.
Şimdi bunu gönderelim.
Sunucu cevap olarak önce protokol numarasını gönderecek; 5.. Hemen ardından 0 göndermişse bağlantı başarılıdır, artık gönderdiğimiz her byte'ı istisnasız hedefe aktaracaktır. Yoksa SOCKS5 hata kodlarını araştırın, onlardan birini göndermiştir.
Şimdi ssl, yani HTTPS sitelere bağlanmak var. SSL istenmişse ve istenmemişse farklı şeyler yapacağız.
Eğer eleman ssl istememişse, oluşturduğumuz NetworkStream üstünden mesaj gönderip alabiliriz. Hiç sorun yok.
Ama eğer eleman ssl istemişse, bunu bir SslStream içine gömüp, adresten auth istiyoruz. Normalde gıcık bir iştir ama en azından bunu, sağolsun .NET Framework bizim için yapıyor.
Neticede "baglanti" alanımız hedefe doğru bir şekilde bağlanmış bir stream oluyor. İşimiz bitti.
Bütün kod;
E biz heçkırız, Tor kullanacağız yahu! Tor bir SOCKS5 proxy'dir, bizi nasıl engellerler?!
Hadi hemen bir Socks5 sınıfı oluşturalım. Ben tembellik yapıyorum aslında. DoS programımın zaten Socks5 portları üstünden aktarım yapma yeteneği var, yani bu class'ın elimde yapılmışı var
Bunu bir Dynamic Link Library, yani dll projesi olarak yapacağız ki diğer projelerimizde hızlıca aktarıverelim.
Class'ı oluşturduktan sonra bilmemiz gereken tek şeyler SOCKS5 proxy'nin adresi ve portu. Bunun için gerekli alanları ve constructor'ı yazalım...
Kod:
public class Socks5Baglanti
{
public string proxyAdres;
public int proxyPort;
public System.Net.Sockets.Socket soket;
public System.IO.Stream baglanti;
public Socks5Baglanti(string proxyAdres,int proxyPort)
: base()
{
this.proxyAdres=proxyAdres;
this.proxyPort = proxyPort;
soket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
}
Ne yaptık? Proxy adres ve portunu kaydettikten sonra sonradan kullanacağımız soketi de hazırlayıverdik. Ama daha hiç bir yere bağlanmadık! Kullanıcı "bağlan" desin öyle bağlanacağız. Yoksa gereksiz timeout'ları kontrol etmemiz gerekir. "baglanti" değerini sonradan kullanacağız. Şimdilik kafanıza takmayın.
Sonra yapacağımız ise sadece "bağlanmak". Bunu adım adım yapacağız.
İlk işimiz, "arkadaş socks versiyonun 5 olmalı, bir tane authentication metodu kabul ediyorum, o da 0, yani auth olmadan kullanmak" demek. Sırayla 5, 1 (1 tane auth türü) ve 0 göndermek yani..
Sadece soketimizi proxy'ye bağladık, sonra dediğim gibi sadece 5, 1 ve 0 byte'larını gönderdik. Şimdi sunucunun cevabını dinleyeceğiz, bu da sadece 2 byte olacak. Ama sonradan daha büyük buffer kullanacağımızdan baştan ben 50 byte'lık bir buffer açıyorum.
Sunucu cevap olarak önce protokolünü tekrar edecek, yani ilk byte 5 gönderecek. İkinci byte, auth olmadan girişi kabul etmişse bu protokol numarasının tekrarı olacak, yani 0, yok kabul etmemişse 255 olacak.
Kod:
soket.Connect(proxyAdres, proxyPort);
soket.Send(new byte[] { 5, 1, 0 });
byte[] buffer = new byte[50];
soket.Receive(buffer);
if (buffer[1] != 0) return false;
....
Bir buffer oluşturduk, o buffer'a okuma yaptık, yaptığımız okumanın 2. byte'ı 0 değilse "yanlış" döndürerek çıktık çünkü bağlanamıyoruz.
Sonra tekrar versiyon numarasını göndeririz tek byte, yani 5. İsteğimiz TCP ile porta bağlanmak ise 1, TCP portu bind etmek ise 2 (TOR bunu desteklemez, ücretsiz hiç bir proxy desteklemez) veya UDP bağlantı kurmak ise 3 göndeririz(TOR UDP'yi de desteklemez.)
Benim amacım TCP portuna bağlanmak şu anda, 1 göndereceğim. Bunun ardından tek bir byte 0 gönderiyoruz. Bu rezerve bir değer, hep göndermek zorundayız.
Sonra da adres gönderim şekli var. IP gönderiyorsak 1, domain adı gönderiyorsak 3, IPv6 gönderiyorsak 4 göndeririz.
Biz domain adresi göndermek istedik, kullanıcıdan string istedik.
Eğer IPv4 veya IPv6 gönderiyorsak bu IP'nin byte'larını sırayla gönderirdik. Ama domain adı her uzunlukta olabileceğinden ilk byte olarak uzunluğunu, ardından da bütün domain adresini gödneriyoruz.
En son da kullanacağımız portu, 2 byte olarak (0-65535 arası her port olabilir) gönderiyoruz bu kadar.
Yani ne diyoruz; öncelikle protokol, sonra bağlantı türü,sonra rezerve olan 0, sonra adres türü.
Kod:
new byte[]{5,1,0,3}
Sonra bunu domain adresinin boyutu ile birleştiriyoruz...
Kod:
new byte[]{5,1,0,3}[B].Concat(new byte[]{(byte)adres.Length})[/B]
Sonra domain'in kendisini yazıyoruz ardına..
Kod:
new byte[] { 5, 1, 0, 3 }.Concat(new byte[] { (byte)adres.Length })[B].Concat(Encoding.ASCII.GetBytes(adres))[/B]
En son da port adresimizi yazalım. Little endian unsigned short olarak yazacağız. Yani önce portumuzun son byte'ını, sonra ilk byte'ını yazıyoruz.
Kod:
new byte[] { 5, 1, 0, 3 }.Concat(new byte[] { (byte)adres.Length }).Concat(Encoding.ASCII.GetBytes(adres)).Concat(new byte[] { (byte)(port / 256), (byte)(port % 256) })
Şimdi bunu gönderelim.
Kod:
soket.Send(new byte[] { 5, 1, 0, 3 }.Concat(new byte[] { (byte)adres.Length }).Concat(Encoding.ASCII.GetBytes(adres)).Concat(new byte[] { (byte)(port / 256), (byte)(port % 256) }).ToArray());
if (buffer[1] != 0) return false;
Sunucu cevap olarak önce protokol numarasını gönderecek; 5.. Hemen ardından 0 göndermişse bağlantı başarılıdır, artık gönderdiğimiz her byte'ı istisnasız hedefe aktaracaktır. Yoksa SOCKS5 hata kodlarını araştırın, onlardan birini göndermiştir.
Şimdi ssl, yani HTTPS sitelere bağlanmak var. SSL istenmişse ve istenmemişse farklı şeyler yapacağız.
Kod:
baglanti = new System.Net.Sockets.NetworkStream(soket);
if (ssl)
{
System.Net.Security.SslStream _stream = new System.Net.Security.SslStream(baglanti);
_stream.AuthenticateAsClient(adres);
baglanti = _stream;
}
return true;
Ama eğer eleman ssl istemişse, bunu bir SslStream içine gömüp, adresten auth istiyoruz. Normalde gıcık bir iştir ama en azından bunu, sağolsun .NET Framework bizim için yapıyor.
Neticede "baglanti" alanımız hedefe doğru bir şekilde bağlanmış bir stream oluyor. İşimiz bitti.
Bütün kod;
Kod:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TCP
{
public class Socks5Baglanti
{
public string proxyAdres;
public int proxyPort;
private System.Net.Sockets.Socket soket;
public System.IO.Stream baglanti;
public Socks5Baglanti(string proxyAdres, int proxyPort)
: base()
{
this.proxyAdres = proxyAdres;
this.proxyPort = proxyPort;
soket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
}
public bool baglan(string adres, int port, bool ssl = false)
{
soket.Connect(proxyAdres, proxyPort);
soket.Send(new byte[] { 5, 1, 0 });
byte[] buffer = new byte[50];
soket.Receive(buffer);
if (buffer[1] != 0) return false;
soket.Send(new byte[] { 5, 1, 0, 3 }.Concat(new byte[] { (byte)adres.Length }).Concat(Encoding.ASCII.GetBytes(adres)).Concat(new byte[] { (byte)(port / 256), (byte)(port % 256) }).ToArray());
if (buffer[1] != 0) return false;
baglanti = new System.Net.Sockets.NetworkStream(soket);
if (ssl)
{
System.Net.Security.SslStream _stream = new System.Net.Security.SslStream(baglanti);
_stream.AuthenticateAsClient(adres);
baglanti = _stream;
}
return true;
}
}
}
Son düzenleme: