Delphi & Windows Firewall
// 7 Haziran 2009 // Delphi, Internet, İşletim Sistemi, Programlama
Firewall temel anlamı ile işletim sistemlerini daha güvenli kılmak için tasarlanmış programlardır.Modern işletim sistemlerinin hemen hemen hepsinde gömülü olarak bulunan bir firewall vardır. Güvenlik duvarı, ateş duvarı gibi isimler alan firewall’lar; makinamızda çalışan uygulamaların internete çıkışlarını denetleyen, dışarıdan içeri gelen TCP/UDP paketlerini çeşitli kurallara göre filtrelemeye çalışan uygulamalardır. Kimi zamanlarda yazdığımız uygulamalar, firewall’lar tarafından güvensiz içerik olarak algılanırlar ve blok edilmeye çalışılırlar. Eğer programınız network ortamında çalışıyor ve ortam bilgisayarları ile çeşitli protokoller üzerinden haberleşiyor ise, yada programınız internet’e erişmek durumunda ise; firewall’larla sıkıntı yaşamış olabilirsiniz.
Yazdığınız bir uygulamanın, uygulamayı geliştirdiğiniz makinada çalıştığı, ancak müşterinin makinasında çalışmadığı; yada erişmek istediğiniz network kaynaklarına erişemediği, internete çıkamadığı durumlarla karşılaştı iseniz, bu makalemizden istifade edebilirsiniz demektir. İşletim sistemi ile birlikte gelen Windows Firewall, nispeten basit bir güvenlik duvarı. Pek fazla ayarı ve detayı yok, ancak yine de paralı muadillerinin yaptıklarını mümkün mertebe yerine getiren bir program.
Bizim makalemiz, işletim sistemi ile birlikte gelen güvenlik duvarının programlanmasına yönelik olacak. Sizde taktir edersiniz ki, piyasada gerek donanımsal gerekse de yazılımsal pek çok farklı firewall mevcut, bizim yazacaklarımız onlara destek vermiyor olacak.
Yukarıdaki resimde, Windows Firewall’un genel ayarlarını görüyoruz. Bu ekranda, firewall’un açık yada kapalı olduğu bilgisi ve exception list’e izin verilip verilmeyeceği ayarını görüyoruz. Exception List, bizim firewall tarafından kontrol edilmesini istemediğimiz, network kaynaklarına yada internete erişimde firewall’un bloklamasından etkilenmeyecek uygulamalarımızın listesidir. Yukarıdaki resimde “Don’t allow exceptions” ayarı, bizim firewall kontrolünden uzakta tuttuğumuz programlarımızın dahi erişimlerinin firewall kontrolü altına yeniden alınabilmesi içindir. Bu ayar genellikle, taşınabilir bilgisayarınızla topluma açık mekanlarda internete bağlandığınız zaman yararlı olur. Aşağıda benim makinamda ki exception list görünüyor:
Windows Firewall ile biz sadece belirlediğimiz programlara değil, aynı zamanda belirlediğimiz bir port numarasına da izin verebiliriz. Bu özellik, genellikle client makinaların herhangi bir makinadaki SQL Server’a ulaşamamaları durumunda kullandığımız bir özellik. Yahut, makinanızda çalışan bir uygulamanın açmak istediği bir port ile internet üzerinden haberleşme yapmak durumunda kullanışlı olabilir. Örneğin, eMule dosya indirme programındaki gibi.
Bu makalemizde, Windows Firewall’dan; izin verilen programların ve izin verilen portların listesinin alınmasını, yeni bir program ve yeni bir port eklenmesini, firewall’un aktif/deaktif edilmesini ve yapılan değişikliklerin en son haline geri alınmasını göstermeye çalışacağız.
Bunun için yine COM programlamanın özelliklerinden yararlanacağız. İşletim sistemi ile birlikte gelen Windows Firewall’u Delphi’miz altında kullanabilmek için aşağıdaki resimde göreceğiniz üzere; gereken type library’i import edeceğiz.
Bu aşamadan sonra, Delphi varsayılan import klasöründe NetFwTypeLib_TLB.pas isminde bir dosya oluşturacaktır. Bu dosya, Windows Firewall nesnelerinin desteklediği arabirimlerin tanımlarını içerir.
Kullanacağımız en önemli arabirim, INetFwMgr isimli arabirim. Tüm erişimlerimizi bu arabirim üzerinden gerçekleştireceğiz. İlk olarak, Windows Firewall’a erişip, firewall’un aktif olup olmadığını sorgulayalım:
procedure TForm1.btnTestClick(Sender : TObject); FireWall : INetFwMgr; begin CoInitialize(nil); FireWall := CreateOLEObject('HNetCfg.FwMgr') as INetFwMgr; if FireWall.LocalPolicy.CurrentProfile.FirewallEnabled then ShowMessage('Firewall is Enabled') else ShowMessage('Firewall is Disabled'); FireWall := nil; CoUnInitialize; end;
Yukarıda örneğimizde Windows Firewall nesnesine HNetCfg.FwMgr ismi üzerinden erişip gerekli kontrollerimizi yaptık. Peki, firewall’da erişim izni verilmiş olan uygulamaların(exception list) listesini nasıl alacağız ? Buyrun ona da yakından bakalım:
procedure TForm1.btnTestClick(Sender : TObject); var FireWall : INetFwMgr; ExceptionList : INetFwAuthorizedApplications; Collection : IEnumVariant; tmp : OleVariant; dummy : Cardinal; begin CoInitialize(nil); FireWall := CreateOLEObject('HNetCfg.FwMgr') as INetFwMgr; ExceptionList := FireWall.LocalPolicy.CurrentProfile.AuthorizedApplications; Collection := ExceptionList._NewEnum as IEnumVariant; while (Collection.Next(1, tmp, dummy) = S_OK) do Memo1.Lines.Add(tmp.Name + '->' + tmp.ProcessImageFileName + '->' + tmp.RemoteAddresses); Collection := nil; ExceptionList := nil; FireWall := nil; CoUnInitialize; end;
Yukarıdaki örneğimiz, INetFwMgr arabiriminin AuthorizedApplications arabirimine ulaşarak daha önce izin verilmiş uygulamarın listesini aldı ve bir TMemo bileşeni içinde gösterdi. Buna benzer bir yapıda, izin verilen port’ların listesini almak için kurabiliriz;
procedure TForm1.btnTestClick(Sender : TObject); var FireWall : INetFwMgr; Collection : IEnumVariant; tmp : OleVariant; dummy : Cardinal; begin CoInitialize(nil); FireWall := CreateOLEObject('HNetCfg.FwMgr') as INetFwMgr; Collection := FireWall.LocalPolicy.CurrentProfile.GloballyOpenPorts._NewEnum as IEnumVariant; while (Collection.Next(1, tmp, dummy) = S_OK) do Memo1.Lines.Add(tmp.Name + '->' + InttoStr(Integer(tmp.Port))); Collection := nil; FireWall := nil; CoUnInitialize; end;
Gördüğünüz gibi karmaşık olmayan, ancak pek de akılda kalıcı olmayan bir yazım tarzına sahip. Hem daha sonralardaki kullanımlarımızda kolaylık olması adına, hemde onlarca satırı müteaddit defalar yazmamak için gelin biz bu fonksiyonaliteyi kapsayacak bir TFireWall sınıfı yazalım:
TFireWallIPVersion = ( Version4 = $00000000, Version6 = $00000001, VersionAny = $00000002, VersionMax = $00000003 ); TFireWallScope = ( ScopeAll = $00000000, ScopeLocalSubnet = $00000001, ScopeCustom = $00000002, ScopeMax = $00000003 ); TFireWallProtocol = ( ProtocolTCP = $00000006, ProtocolUDP = $00000011 ); TAuhtorizedApp = class private fName, fRemoteAddress, fProcessImageFileName : String; fEnabled : Boolean; fIpVersion : TFireWallIPVersion; fScope : TFireWallScope; public constructor Create( const AName, ARemoteAddresses, AProcessImageFileName : String; const AEnabled : Boolean; const AScope : TFireWallScope; const AIpVersion : TFireWallIPVersion ); property Name : String read fName; property RemoteAddresses : String read fRemoteAddress; property ProcessImageFileName : String read fProcessImageFileName; property Enabled : Boolean read fEnabled; property Scope : TFireWallScope read fScope; property IpVersion : TFireWallIPVersion read fIpVersion; end; TOpenPort = class private fName, fRemoteAddress : String; fEnabled, fBuiltIn : Boolean; fIpVersion : TFireWallIPVersion; fScope : TFireWallScope; fProtocol : TFireWallProtocol; fPort : Integer; public constructor Create( const AName, ARemoteAddresses : String; const AEnabled : Boolean; const AScope : TFireWallScope; const AIpVersion : TFireWallIPVersion; const AProtocol : TFireWallProtocol; const APort : Integer ); property Name : String read fName; property RemoteAddresses : String read fRemoteAddress; property Enabled : Boolean read fEnabled; property Scope : TFireWallScope read fScope; property IpVersion : TFireWallIPVersion read fIpVersion; property Protocol : TFireWallProtocol read fProtocol; property Port : Integer read fPort; end; TFireWall = class private fFireWall : INetFwMgr; fLocalPolicy : INetFwPolicy; fProfile : INetFwProfile; fRemoteAdminSettings : INetFwRemoteAdminSettings; fIcmpSettings : INetFwIcmpSettings; fGloballyOpenPorts : INetFwOpenPorts; fServices : INetFwServices; fAuthorizedApplications : INetFwAuthorizedApplications; function GetFireWallEnabled : Boolean; procedure SetFireWallEnabled(const Value : Boolean); function GetAllowExceptions : Boolean; procedure SetAllowExceptions(const Value : Boolean); function GetAllowNotifications : Boolean; procedure SetAllowNotifications(const Value : Boolean); function GetAuthorizedApplications : TStrings; function GetOpenPorts : TStrings; public constructor Create; destructor Destroy; override; procedure Restore; function ApplicationExists(const APath : String) : Boolean; function PortExists(const APort : Integer; const AProtocol : TFireWallProtocol) : Boolean; procedure AddApplication(const AName, APath : String); procedure RemoveApplication(const APath : String); procedure AddPort(const AName : String; const APort : Integer; const APortProtocol : TFireWallProtocol); procedure RemovePort(const APort : Integer; const APortProtocol : TFireWallProtocol); property Enabled : Boolean read GetFireWallEnabled write SetFireWallEnabled; property AllowExceptions : Boolean read GetAllowExceptions write SetAllowExceptions; property AllowNotifications : Boolean read GetAllowNotifications write SetAllowNotifications; property AuthorizedApplications : TStrings read GetAuthorizedApplications; property OpenPorts : TStrings read GetOpenPorts; end; implementation { TFireWall } constructor TFireWall.Create; begin inherited; CoInitialize(nil); fFireWall := CreateOLEObject('HNetCfg.FwMgr') as INetFwMgr; if fFireWall <> nil then begin fLocalPolicy := fFireWall.LocalPolicy; fProfile := fFireWall.LocalPolicy.CurrentProfile; fRemoteAdminSettings := fFireWall.LocalPolicy.CurrentProfile.RemoteAdminSettings; fIcmpSettings := fFireWall.LocalPolicy.CurrentProfile.IcmpSettings; fGloballyOpenPorts := fFireWall.LocalPolicy.CurrentProfile.GloballyOpenPorts; fServices := fFireWall.LocalPolicy.CurrentProfile.Services; fAuthorizedApplications := fFireWall.LocalPolicy.CurrentProfile.AuthorizedApplications; end else raise Exception.Create('Firewall''a ulaşılamıyor.!'); end; destructor TFireWall.Destroy; begin fFireWall := nil; fLocalPolicy := nil; fProfile := nil; fRemoteAdminSettings := nil; fIcmpSettings := nil; fGloballyOpenPorts := nil; fServices := nil; fAuthorizedApplications := nil; CoUninitialize; inherited; end; procedure TFireWall.AddApplication(const AName, APath: String); var app : INetFwAuthorizedApplication; begin if Trim(AName) = '' then raise Exception.Create('Lütfen bir isim belirtiniz.!'); if not FileExists(APath) then raise Exception.Create('Belirtilen dosya bulunamadı.!'); if not AllowExceptions then raise Exception.Create('Uygulama ekleme seçeneği devre dışı.!'); app := CreateOleObject('HNetCfg.FwAuthorizedApplication') as INetFwAuthorizedApplication; try app.Name := AName; app.ProcessImageFileName := APath; app.IpVersion := TOleEnum(VersionAny); app.RemoteAddresses := '*'; app.Scope := TOleEnum(ScopeAll); app.Enabled := true; fAuthorizedApplications.Add(app); finally app := nil; end; end; procedure TFireWall.AddPort(const AName: String; const APort: Integer; const APortProtocol: TFireWallProtocol); var port : INetFwOpenPort; begin if Trim(AName) = '' then raise Exception.Create('Lütfen bir isim belirtiniz.!'); port := CreateOleObject('HNetCfg.FwOpenPort') as INetFwOpenPort; try port.Name := AName; port.IpVersion := TOleEnum(VersionAny); port.Protocol := TOleEnum(APortProtocol); port.Scope := TOleEnum(ScopeAll); port.Port := APort; port.RemoteAddresses := '*'; port.Enabled := true; fGloballyOpenPorts.Add(port); finally port := nil; end; end; function TFireWall.ApplicationExists(const APath : String): Boolean; var sList : TStrings; iCounter : Integer; begin Result := false; sList := AuthorizedApplications; if sList <> nil then for iCounter := 0 to sList.Count - 1 do if sList.Objects[iCounter] <> nil then if sList.Objects[iCounter] is TAuhtorizedApp then if TAuhtorizedApp(sList.Objects[iCounter]).ProcessImageFileName = APath then begin Result := true; Break; end; end; function TFireWall.GetAllowExceptions: Boolean; begin Result := false; if fProfile <> nil then Result := not fProfile.ExceptionsNotAllowed; end; function TFireWall.GetAllowNotifications: Boolean; begin Result := false; if fProfile <> nil then Result := fProfile.NotificationsDisabled; end; function TFireWall.GetAuthorizedApplications: TStrings; var apps : IEnumVariant; app : OleVariant; dummy : Cardinal; iCounter : Integer; begin Result := TStringList.Create; apps := fAuthorizedApplications._NewEnum as IEnumVariant; while (apps.Next(1, app, dummy) = S_OK) do begin Result.AddObject( app.Name, TAuhtorizedApp.Create( app.Name, app.RemoteAddresses, app.ProcessImageFileName, app.Enabled, TFireWallScope(app.Scope), TFireWallIPVersion(app.IpVersion) ) ); end; apps := nil; end; function TFireWall.GetFireWallEnabled: Boolean; begin Result := false; if fProfile <> nil then Result := fProfile.FirewallEnabled; end; function TFireWall.GetOpenPorts: TStrings; var ports : IEnumVariant; port : OleVariant; dummy : Cardinal; iCounter : Integer; begin Result := TStringList.Create; ports := fProfile.GloballyOpenPorts._NewEnum as IEnumVariant; while (ports.Next(1, port, dummy) = S_OK) do begin Result.AddObject( port.Name, TOpenPort.Create( port.Name, port.RemoteAddresses, port.Enabled, TFireWallScope(port.Scope), TFireWallIpVersion(port.IpVersion), TFireWallProtocol(port.Protocol), Integer(port.Port) ) ); end; ports := nil; end; function TFireWall.PortExists(const APort: Integer; const AProtocol : TFireWallProtocol): Boolean; var sList : TStrings; iCounter : Integer; begin Result := false; sList := OpenPorts; if sList <> nil then for iCounter := 0 to sList.Count - 1 do if sList.Objects[iCounter] <> nil then if sList.Objects[iCounter] is TOpenPort then if (TOpenPort(sList.Objects[iCounter]).Port = APort) and (TOpenPort(sList.Objects[iCounter]).Protocol = AProtocol) then begin Result := true; Exit; end; end; procedure TFireWall.RemoveApplication(const APath : String); begin if not FileExists(APath) then raise Exception.Create('Belirtilen dosya bulunamadı.!'); if fAuthorizedApplications <> nil then fAuthorizedApplications.Remove(APath); end; procedure TFireWall.RemovePort(const APort: Integer; const APortProtocol: TFireWallProtocol); begin if fGloballyOpenPorts <> nil then fGloballyOpenPorts.Remove(APort, TOleEnum(APortProtocol)); end; procedure TFireWall.Restore; begin if fFireWall <> nil then fFireWall.RestoreDefaults; end; procedure TFireWall.SetAllowExceptions(const Value: Boolean); begin if fProfile <> nil then fProfile.ExceptionsNotAllowed := Value; end; procedure TFireWall.SetAllowNotifications(const Value: Boolean); begin if fProfile <> nil then fProfile.NotificationsDisabled := Value; end; procedure TFireWall.SetFireWallEnabled(const Value: Boolean); begin if fProfile <> nil then fProfile.FirewallEnabled := Value; end; { TAuhtorizedApp } constructor TAuhtorizedApp.Create(const AName, ARemoteAddresses, AProcessImageFileName: String; const AEnabled: Boolean; const AScope: TFireWallScope; const AIpVersion: TFireWallIPVersion); begin inherited Create; fName := AName; fRemoteAddress := ARemoteAddresses; fProcessImageFileName := AProcessImageFileName; fEnabled := AEnabled; fScope := AScope; fIpVersion := AIpVersion; end; { TOpenPort } constructor TOpenPort.Create(const AName, ARemoteAddresses: String; const AEnabled : Boolean; const AScope: TFireWallScope; const AIpVersion: TFireWallIPVersion; const AProtocol: TFireWallProtocol; const APort: Integer); begin inherited Create; fName := AName; fRemoteAddress := ARemoteAddresses; fEnabled := AEnabled; fScope := AScope; fIpVersion := AIpVersion; fProtocol := AProtocol; fPort := APort; end;
Yukarıdaki kod örneğimizde; TAuhtorizedApp ve TOpenPort isimli sınıfları görüyoruz. Bu sınıflar; NetFwTypeLib_TLB.pas dosyası içindeki INetFwAuthorizedApplication ve INetFwOpenPort interface’lerinin karşılıkları olarak üretilmişler ve TFireWall sınıfımız içinde otomatikman oluşturulmuşlardır. Bu hâli ile TFireWall sınıfımız, Windows FireWall üzerinden izin verilen uygulama ve portların listesini alabildiği gibi, yeni uygulamalar ve portlar ekleyebilme gücüne sahiptir. Aynı zamanda Firewall’u açıp kapatabilen, izin verilen uygulamaların izinlerini devre dışı bırakabilen ve Windows Firewall’un herhangi bir uygulamayı blokladığında bizi uyarmasını sağlayan mekanizmayı kontrol edebildiğimiz bir sınıf olan TFireWall’un işinize yaramasını ümit ediyorum.
Saygılar, sevgiler..
bu component guzel dusunulmus ama iyi niyetli insanlar icin. ayni yontemlerle trojanlar da kendilerine acik kapi olusturabilirler. Windows Firewall bu acidan pek de guzel bi secenek degil
Bilginin her türlüsü iyiye ve kötüye kullanılabilir elbette. O da insanların ahlaki yaklaşımları ile ilgili. Biz bildiklerimizi paylaşır ve iyi hususlarda kullanmalarını ümit edebiliriz sadece.
Valla tuğrul abim iyi niyetli adamdır nerden bulmuş bilmiyorum ama iyi bulmuş iyide kullanır bu komponenti.
Sağolasın selmanım Ama component’i bir yerden bulmadım, benim imalatım
Gerçekten class yazımını ve kullanımını öğreten iyi bir çalışma, geliştirilecek bir çok programa esin kaynağı olabilir. Emeğinize sağlık. Teşekkürler.
Bir cirpida okanabilecek,bilgilendirici,guzel bir makele olmus.Tesekkurler
Walla Tuğrulcuğum,
senin yazılarını okurken
delphiyi tam kavramadan bırakmaya yöneldiğimi düşünerek üzülüyorum..
O zaman hobi olarak da olsa şöyle bir geri dönüş yapabilirsin gürcanım