Reject_Connections_on_Port_1433

Snippet Name: Reject_Connections_on_Port_1433

Tags:

Created Date: 2025-06-16 13:12:49
Last Modified Date: 2025-05-31 10:32:03

Dependencies:

DBA Notes:

Sample Output:

Title: Reject Connections on Port 1433
Author: user
in SQL server, i have enabled my server to listen to two ports, 48155 and port 1433. can we create a server trigger to reject connecitosn with an error if they connect to port 1433?

Author: ChatGPT
SQL Server does not provide a built-in mechanism to directly determine the port number on which a connection was made within a server trigger. However, you can achieve this goal using a combination of Extended Events and a server-side process.

### Why Triggers Alone Won't Work
SQL Server triggers (`LOGON` triggers) can intercept login events but do not expose details about the port used for the connection. They provide access to the session and login context but not the network details.

### Alternative Approach
You can use Extended Events to capture connections on port 1433 and deny them programmatically. Here's how:

1. **Set Up an Extended Event to Log Connections**  
   Use the `sqlserver.rpc_starting` or `sqlserver.connectivity_ring_buffer_recorded` event to capture connections and log the relevant details, including the port.

2. **Monitor Extended Event Output**  
   Continuously monitor the Extended Event output for connections on port 1433.

3. **Programmatically Disconnect Users**  
   Use a script or job to detect connections on port 1433 and execute the `KILL` command to disconnect such sessions.

### Implementing a LOGON Trigger
Although triggers can't detect the port directly, you can implement a LOGON trigger to reject connections based on indirect factors (e.g., application name, IP address, etc.) if those can correlate with port usage. Here's an example:

```sql
CREATE TRIGGER Reject1433Connections
ON ALL SERVER
FOR LOGON
AS
BEGIN
    DECLARE @ErrorMessage NVARCHAR(255) = N'Connections to port 1433 are not allowed.'
    DECLARE @Login NVARCHAR(100) = ORIGINAL_LOGIN()
    DECLARE @AppName NVARCHAR(100) = APP_NAME()

    -- Add your conditions here to reject connections
    -- For example, if your port 1433 users use a specific app:
    IF @AppName = 'YourBlockedAppName'
    BEGIN
        ROLLBACK;
        THROW 50001, @ErrorMessage, 1;
    END
END;
GO
```

### Preferred Solution
If rejecting connections solely based on the port is critical, manage this outside SQL Server using:

1. **Firewall Rules**  
   Configure your firewall to allow connections only on port 48155 and block port 1433.

2. **SQL Server Configuration**  
   Disable port 1433 in SQL Server entirely to ensure no connections are allowed.

3. **Proxy or Load Balancer**  
   Use a network proxy or load balancer to filter connections based on port and route them appropriately.

If you need further assistance setting up one of these solutions, let me know!

Author: user
that example is an extension of the classic example of rejecting based on applciaiton name, but never actually tests the port

Author: ChatGPT
You're correct; SQL Server's LOGON triggers can't directly detect the port number. The underlying limitation is that SQL Server does not expose the port number to the session context available to the trigger. 

To achieve port-based rejection, you would need to rely on a method outside the direct capabilities of a LOGON trigger. Let me walk you through a practical alternative solution:

---

### Alternative Method: Using Extended Events and a Custom Monitoring Job
Since SQL Server itself does not expose the port directly to LOGON triggers, you can use Extended Events to detect connections and log details, including the port number. Then, use a scheduled job or process to reject or terminate unwanted sessions.

---

#### Step 1: Configure Extended Events to Log Connections
You can create an Extended Events session to capture the port number from incoming connections:

```sql
CREATE EVENT SESSION [ConnectionPortMonitor]
ON SERVER
ADD EVENT sqlserver.connectivity_ring_buffer_recorded(
    ACTION (sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.database_id, sqlserver.session_id)
    WHERE ([sqlserver].[client_tcp_port] = 1433))
ADD TARGET package0.event_file(SET filename = N'ConnectionPortMonitor.xel', max_file_size = 5, max_rollover_files = 2)
WITH (MAX_MEMORY = 4096 KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY = 30 SECONDS, MAX_EVENT_SIZE = 0 KB, MEMORY_PARTITION_MODE = NONE, TRACK_CAUSALITY = OFF, STARTUP_STATE = OFF);
GO

ALTER EVENT SESSION [ConnectionPortMonitor] ON SERVER STATE = START;
GO
```

This Extended Event captures details about connections, including their port, and writes them to an `.xel` file.

---

#### Step 2: Create a Job to Monitor and Disconnect
Use a SQL Agent job or a PowerShell script to monitor the Extended Events log for connections on port 1433 and disconnect them:

1. **Query the XEL File**  
   Use `sys.fn_xe_file_target_read_file` to read the `.xel` file and extract sessions connected to port 1433.

2. **Terminate Sessions**  
   Use the `KILL` command to terminate the identified sessions.

Here's a script to automate this:

```sql
-- Read Extended Event logs for connections on port 1433
WITH Port1433Connections AS (
    SELECT
        CAST(event_data AS XML) AS EventData
    FROM sys.fn_xe_file_target_read_file('ConnectionPortMonitor*.xel', NULL, NULL, NULL)
)
SELECT 
    EventData.value('(event/action[@name="session_id"]/value)[1]', 'INT') AS SessionID
INTO #ConnectionsToKill
FROM Port1433Connections;

-- Kill the sessions connected to port 1433
DECLARE @SessionID INT;

WHILE EXISTS (SELECT 1 FROM #ConnectionsToKill)
BEGIN
    SELECT TOP 1 @SessionID = SessionID FROM #ConnectionsToKill;
    BEGIN TRY
        EXEC ('KILL ' + CAST(@SessionID AS NVARCHAR(10)));
    END TRY
    BEGIN CATCH
        PRINT 'Unable to kill session: ' + CAST(@SessionID AS NVARCHAR(10));
    END CATCH;

    DELETE FROM #ConnectionsToKill WHERE SessionID = @SessionID;
END

DROP TABLE #ConnectionsToKill;
```

---

#### Step 3: (Optional) Automate the Job
Schedule the script in SQL Server Agent to run frequently (e.g., every minute) to continuously enforce the rejection of connections on port 1433.

---

#### Step 4: Consider Blocking Port 1433 at the Network Layer
While the above solution works, the most efficient and reliable way to enforce port-based access control is at the network layer. For example:

1. **Firewall Rules**  
   Block incoming connections to port 1433.
   
2. **SQL Server Configuration**  
   Remove port 1433 from your SQL Server configuration entirely by disabling it in the SQL Server Network Configuration.

---

Let me know if you need assistance setting up any of these steps!


Leave a Reply