Post

使用ping实现临时开启22端口

Using Ping as a Key to Temporarily Enable SSH:22 Port for Secure Remote SSH Access

When configuring firewall policies for SSH:22 access, we often set the server to accept connections only from a specific IP (such as a company IP). But what if you need to access the server while traveling or from home?

Common solutions include:

  1. Using a VPN to log in to the host.
  2. Using a ping key to temporarily enable the remote host’s SSH:22 port.

Today, we’ll discuss the second solution and explain how to use a ping key to temporarily open SSH:22 access.

Principle:

The recent module in iptables is a powerful tool that can track the IP addresses of recent visitors, and it is commonly used to implement DROP policies to mitigate syn-flood and DDoS attacks. However, in this example, we utilize the recent module in a different way by creating an ACCEPT policy. We set up an sshKeyList to track IP addresses that send specific ICMP echo request (ping) packets. When an IP address in this list reaches a predefined hit count within a specified time frame, the server allows that IP to access SSH:22. Our goal is to ensure that our current client’s dynamic IP is recorded in this list. This can be achieved using the ping command, which sends packets containing the source IP to the remote server. In this way, the ping command functions as a key, temporarily unlocking SSH:22 for the client’s IP address.

Solution:

The key must have a certain level of security and not be easily guessed. Here’s how we create the key:

  • Use the length module to match the total packet length.
  • Define a custom ping packet size.
  • Define a custom number of ping attempts.
  • Ensure the login to SSH:22 occurs within a specified time.

To summarize, the server temporarily grants SSH:22 access only if it receives a ping packet of a specific size and count within a certain time frame.

Implementation:

Send a ping packet of 1050 bytes, five times from any client. The server will then automatically open SSH:22 access for this client for 30 seconds.

Note: ICMP packet structure: IP header (20 bytes) + ICMP header (8 bytes) + Data (1050 bytes)

Calculation: The server receives an ICMP packet of total size 20 + 8 + 1050 = 1078 bytes.

Rules: We need five rules in total:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Rule 1: Accept ping packets of 1078 bytes and record the source IP in sshKeyList.
# -A INPUT: Append this rule to the INPUT chain
# -p icmp: Match ICMP protocol packets
# -m icmp --icmp-type 8: Match ICMP echo request (ping)
# -m length --length 1078: Match packets with a total length of 1078 bytes
# -m recent --name sshKeyList --set: Add the source IP to the recent list named sshKeyList
# -j ACCEPT: Accept the packet
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -m length --length 1078 -m recent --name sshKeyList --set -j ACCEPT

# Rule 2: If hit count reaches 6 within 30 seconds, drop new SSH:22 connections.
# -A INPUT: Append this rule to the INPUT chain
# -p tcp: Match TCP protocol packets
# -m tcp --dport 22 --syn: Match TCP packets destined for port 22 (SSH) with the SYN flag set (new connections)
# -m recent --name sshKeyList --rcheck --seconds 30 --hitcount 6: Check if the source IP is in the sshKeyList with at least 6 hits within the last 30 seconds
# -j DROP: Drop the packet
iptables -A INPUT -p tcp -m tcp --dport 22 --syn -m recent --name sshKeyList --rcheck --seconds 30 --hitcount 6 -j DROP

# Rule 3: If hit count reaches 5 within 30 seconds, accept new SSH:22 connections.
# -A INPUT: Append this rule to the INPUT chain
# -p tcp: Match TCP protocol packets
# -m tcp --dport 22 --syn: Match TCP packets destined for port 22 (SSH) with the SYN flag set (new connections)
# -m recent --name sshKeyList --rcheck --seconds 30 --hitcount 5: Check if the source IP is in the sshKeyList with exactly 5 hits within the last 30 seconds
# -j ACCEPT: Accept the packet
iptables -A INPUT -p tcp -m tcp --dport 22 --syn -m recent --name sshKeyList --rcheck --seconds 30 --hitcount 5 -j ACCEPT

# Rule 4: Accept established connections.
# -A INPUT: Append this rule to the INPUT chain
# -m state --state ESTABLISHED: Match packets that are part of an already established connection
# -j ACCEPT: Accept the packet
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT

# Rule 5: Default drop rule.
# -A INPUT: Append this rule to the INPUT chain
# -j DROP: Drop all packets that do not match previous rules
iptables -A INPUT -j DROP

Testing:

Windows: Default ping attempts: 4 times. Default packet size: 32 bytes.

1
2
3
4
5
6
7
8
C:\Users\Administrator>ping 192.168.137.66 -l 1050 -n 5

Pinging 192.168.137.66 with 1050 bytes of data:
Reply from 192.168.137.66: bytes=1050 time<1ms TTL=64
Reply from 192.168.137.66: bytes=1050 time<1ms TTL=64
Reply from 192.168.137.66: bytes=1050 time<1ms TTL=64
Reply from 192.168.137.66: bytes=1050 time<1ms TTL=64
Reply from 192.168.137.66: bytes=1050 time<1ms TTL=64

Linux: Default ping attempts: unlimited. Default packet size: 56 bytes.

1
2
3
4
5
6
7
[root@martin ~]# ping 192.168.137.66 -s 1050 -c 5
PING 192.168.137.66 (192.168.137.66) 1050(1078) bytes of data.
1058 bytes from 192.168.137.66: icmp_seq=1 ttl=64 time=0.711 ms
1058 bytes from 192.168.137.66: icmp_seq=2 ttl=64 time=1.00 ms
1058 bytes from 192.168.137.66: icmp_seq=3 ttl=64 time=0.629 ms
1058 bytes from 192.168.137.66: icmp_seq=4 ttl=64 time=1.32 ms
1058 bytes from 192.168.137.66: icmp_seq=5 ttl=64 time=1.02 ms

Once done, you can log in via SSH (within 30 seconds, so act quickly). With the --state ESTABLISHED -j ACCEPT rule in place, you don’t have to worry about being disconnected. Secure remote SSH access management is that simple!

Source: 博客园

This post is licensed under CC BY 4.0 by the author.