web-dev-qa-db-fra.com

Restreindre une connexion SQL Server à une adresse IP spécifique

Je souhaite restreindre les connexions à mon instance SQL Server à des adresses IP spécifiques. Je souhaite empêcher toute connexion à partir d'une adresse IP, à l'exception d'une liste spécifique. Est-ce quelque chose qui peut être configuré dans l'instance ou la base de données SQL Server?

17
mohammedn

Cela ressemble à quelque chose que vous feriez en utilisant le Pare-feu Windows (vous pouvez bloquer les ports SQL Server et autoriser des exceptions pour certaines adresses IP).

Vous pouvez le faire avec quelque chose comme un déclencheur de connexion qui vérifie l'adresse IP à l'aide de sys.dm_exec_connections mais je pense que c'est une option beaucoup moins souhaitable que de bloquer le trafic.

Certainement beaucoup plus difficile à faire au niveau de la base de données.

22
Aaron Bertrand

J'ai écrit cette fonctionnalité pour interdire automatiquement une adresse IP qui a fait plus de X ( @ FailedLoginAttempts ) tentatives de connexion à partir de la même adresse IP. Il est basé sur les journaux d'erreurs SQL Server. J'utilise Windows Server 2008 et SQL Server 2008 R2.

Sachez que si vous n'avez pas parcouru vos journaux d'erreurs SQL Server depuis un certain temps, vous pouvez obtenir un grand nombre d'adresses IP et cela peut prendre un peu de temps pour tout traiter. Comme je l'exécute toutes les 10 minutes, l'ensemble du processus prend environ 4 à 5 secondes.

Pas

  1. Assurez-vous que vous enregistrez les tentatives infructueuses. Dans SQL Server Management Studio (SSMS), cliquez avec le bouton droit sur votre instance (au-dessus de vos bases de données) Propriétés Sécurité Audit de connexion . Assurez-vous que le bouton radio pour [Connexions échouées uniquement] || [Connexions échouées et réussies] est sélectionné.
  2. Créer la table pour stocker les adresses IP interdites

    /* Create table to store banned IP addresses */
    USE [YourDB]
    GO
    
    CREATE TABLE [dbo].[autobanned_ipaddesses](
        [id] [int] IDENTITY(1,1) NOT NULL,
        [ipaddress] [varchar](50) NOT NULL,
        [attacked_on] [datetime2](2) NOT NULL,
        [banned_on] [datetime2](7) NOT NULL,
        [number_login_attempts] [int] NULL,
     CONSTRAINT [PK_autobanned_ipaddesses] PRIMARY KEY CLUSTERED
    ([id] ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80) ON [PRIMARY]) ON [PRIMARY]
    
    ALTER TABLE [dbo].[autobanned_ipaddesses] ADD  CONSTRAINT   [DF_autobanned_ipaddesses_banned_on]  DEFAULT (getdate()) FOR [banned_on]
    
  3. Créez le processus pour ajouter automatiquement des adresses IP au pare-feu. Personnellement, j'ai placé ce code dans un travail d'agent exécuté toutes les 10 minutes. Notez également que ce processus utilise xp_cmdshell . Je ne veux certainement pas débattre des avantages d'activer ou de désactiver cette fonctionnalité. À chacun, mais mon script ne fonctionnera pas sans cette fonctionnalité. Si vous ne l'avez pas activé ici est un bon lien pour vous aider.

    USE [YourDB]
        DECLARE @T TABLE(LogDate datetime,ProcessInfo varchar(200),Text varchar(max))
        DECLARE @T2 TABLE(LogDate datetime,ProcessInfo varchar(200),IPAddress varchar(max))
        DECLARE @T3 TABLE(LogDate datetime,IPAddress varchar(max))
        DECLARE @IPAddress varchar(50),@LogDate datetime,@NumLoginAttempts int,@CmdExc varchar(300),@FailedLoginAttempts int=10
    
        BEGIN /* Get error log records with failed login attempt data */
            INSERT INTO @T
            EXEC sp_readerrorlog 0,1,'Could not find a login matching the name provided'
            INSERT INTO @T
            EXEC sp_readerrorlog 0,1,'An error occurred while evaluating the password'
        END
    
        BEGIN /* Get the IP address from T*/
            INSERT INTO @T2
            SELECT LogDate,ProcessInfo,REPLACE(REPLACE( SUBSTRING(Text, PATINDEX ('%[0-9].%[0-9].%[0-9].[0-9]%',Text)-2,50),']',''),':','') FROM @T
        END
    
        BEGIN /* Get the NEW ip addresses from T2*/
            INSERT INTO @T3
            SELECT CONVERT(varchar(10),LogDate,101) LogDate,IPAddress from @T2 T
            WHERE NOT EXISTS(SELECT * FROM autobanned_ipaddesses ai WHERE ai.ipaddress=T.IPAddress)
            GROUP BY CONVERT(varchar(10),LogDate,101),IPAddress
            HAVING  COUNT(LogDate)>@FailedLoginAttempts
            ORDER BY IPAddress
        END
    
        BEGIN /* Validate that T3 has records, if not skip the firewall add */
            IF (SELECT COUNT(*) FROM @T3)=0
            BEGIN
                GOTO ExitWithoutCycle
            END
        END
    
        BEGIN /* Loop through T3 and add each entry to the windows firewall */
            WHILE EXISTS(SELECT * FROM @T3)
            BEGIN
                SELECT TOP(1) @LogDate=LogDate, @IPAddress=IPAddress FROM @T3
                SELECT @NumLoginAttempts=COUNT(*) FROM @T2 WHERE IPAddress=@IPAddress
                    INSERT INTO autobanned_ipaddesses (attacked_on,ipaddress,number_login_attempts) VALUES(@LogDate,@IPAddress,@NumLoginAttempts)
                    SET @CmdExc = 'netsh advfirewall firewall add rule name="Autobanned IP - SQL Attacked '+@IPAddress+'" dir=in action=block enable="yes" remoteip='+@IPAddress+' protocol=any interfacetype=any'
                    EXEC master..xp_cmdshell @CmdExc
                DELETE @T3 WHERE IPAddress=@IPAddress
            END
        END
        /* sp_cycle_errorlog archives the current error log. */
        EXEC sp_cycle_errorlog
        ExitWithoutCycle:
    

Je comprends que ce n'est pas une solution parfaite, car cela ne fonctionne qu'avec les adresses IP IPv4 et ne regarde que les tentatives de connexion effectuées via probablement le port 1433 en fonction de votre configuration. Cependant, cela m'a aidé à identifier et à bloquer plus de 100 adresses IP en une semaine (principalement en Chine et à Hong Kong, mais j'ai bloqué le Department of Homeland Security).

[~ # ~] tangente [~ # ~] - Une fois que j'ai exécuté cela pendant une semaine, j'ai rapidement réalisé qu'il y avait une bonne quantité de modèles dans les plages nettes des adresses IP. J'ai trouvé cet outil pour être le plus utile pour déterminer qui et d'où venaient ces hits. Ce qui est génial avec ce site Web, c'est qu'une fois que vous obtenez l'emplacement de l'adresse IP, en dessous, vous pouvez saisir à nouveau l'adresse IP et obtenir la plage nette de l'adresse IP. Par exemple (désolé la Chine), j'ai trouvé que 59.53.67.13 avait une plage nette de 59.0.0.0 - 59.255.255.255. Cela étant dit, j'ai créé une fonction manuelle pour bloquer toute la plage nette et supprimer toutes les règles du pare-feu Windows qui contenaient déjà des adresses IP dans cette plage.

    USE [YourDB]

    DECLARE @CmdExc varchar(300)
    DECLARE @NetRange varchar(50)='59.0.0.0 - 59.255.255.255'

    DECLARE @NetRangeFrom varchar(20),@NetRangeTo varchar(20),@IPAddress varchar(20)
    DECLARE @IPPart2From int,@IPPart2To int
    DECLARE @IPPartSearch2From int,@IPPartSearch2To int

    DECLARE @T Table (ipaddress varchar(20))

    SET @NetRange=REPLACE(@NetRange,' ','')
    SELECT @NetRangeFrom=LTRIM(RTRIM(SUBSTRING(@NetRange,1,CHARINDEX('-',@NetRange)-1)))
    SELECT @NetRangeTO=LTRIM(RTRIM(SUBSTRING(@NetRange,CHARINDEX('-',@NetRange)+1,50)))
    SELECT @IPPartSearch2From=CAST(PARSENAME(@NetRangeFrom,3) as int)
    SELECT @IPPartSearch2To=CAST(PARSENAME(@NetRangeTo,3) as int)

    INSERT INTO @T
    select ai.ipaddress from autobanned_ipaddesses ai where LTRIM(ai.ipaddress) like SUBSTRING(@NetRangeFrom,1,CHARINDEX('.',@NetRangeFrom,1))+'%' AND PARSENAME(LTRIM(RTRIM(ai.ipaddress)),3) BETWEEN @IPPartSearch2From AND @IPPartSearch2To

    SET @CmdExc = 'netsh advfirewall firewall add rule name="AB SQL Attacked '+@NetRange+'" dir=in action=block enable="yes" remoteip='+@NetRange
    EXEC master..xp_cmdshell @CmdExc
    WHILE EXISTS(SELECT * from @T)
    BEGIN
        SELECT TOP(1) @IPAddress=ipaddress from @T
        SET @CmdExc = 'netsh advfirewall firewall delete rule name="Autobanned IP - SQL Attacked '+@IPAddress+'"'
        EXEC master..xp_cmdshell @CmdExc
        DELETE TOP(1) FROM @T
    END

J'ai hâte de recevoir des commentaires qui amélioreront cette fonctionnalité.

20
Matt Smith
  1. Utilisez un pare-feu externe comme Baracuda ou F5 - Meilleure option pour réduire la charge sur le serveur Windows.
  2. Paramètres du pare-feu Windows - Lorsque vous ne pouvez pas faire ce qui précède, définissez les paramètres du pare-feu entrant et ouvrez le port 1433 et dans l'onglet Ordinateur distant, entrez votre adresse IP source.
  3. Au niveau de la mise en réseau SQL Server - Configuration réseau SQL Server * → Avancé SPN NTLM acceptés . Ajoutez les noms de domaine ici.
  4. Suivez procédure de Matt Smith avec déclencheur
1
Ashburn RK

Je suppose que vous pourriez écrire un déclencheur d'ouverture de session comme décrit ici qui vérifie d'où ils se connectent, mais je suggère qu'il serait préférable d'utiliser un pare-feu.

1
Hans Olsson