Delphi & Windows Firewall
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..


Mustafa
on Ekim 1st, 2009
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
Tuğrul HELVACI
on Ekim 2nd, 2009
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.
Selman Erol
on Ekim 6th, 2009
Valla tuğrul abim iyi niyetli adamdır nerden bulmuş bilmiyorum ama iyi bulmuş iyide kullanır bu komponenti.
Tuğrul HELVACI
on Ekim 9th, 2009
Sağolasın selmanım
Ama component’i bir yerden bulmadım, benim imalatım
Önder Önvermez
on Aralık 1st, 2009
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.
Azat Cicek
on Aralık 3rd, 2009
Bir cirpida okanabilecek,bilgilendirici,guzel bir makele olmus.Tesekkurler
Gürcan
on Temmuz 19th, 2010
Walla Tuğrulcuğum,
senin yazılarını okurken
delphiyi tam kavramadan bırakmaya yöneldiğimi düşünerek üzülüyorum..
Tuğrul HELVACI
on Temmuz 19th, 2010
O zaman hobi olarak da olsa şöyle bir geri dönüş yapabilirsin gürcanım