001/* 002 * Copyright 2026 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.util; 017 018import java.io.IOException; 019import java.net.InetAddress; 020import java.net.InetSocketAddress; 021import java.net.NoRouteToHostException; 022import java.net.Proxy; 023import java.net.Socket; 024import java.net.SocketAddress; 025import java.util.regex.Pattern; 026 027/** 028 * A socket implementation that will block connection to a set of IP address 029 */ 030public class IPRestrictedSocket extends Socket 031{ 032 private Pattern _pattern; 033 /** 034 * Create a socket that block connection to a set of IP address. 035 * @param pattern a regex to match against IP address (v4 or v6). Any address that matches the regex will be block. 036 */ 037 public IPRestrictedSocket(Pattern pattern) 038 { 039 super(); 040 _pattern = pattern; 041 } 042 043 /** 044 * Create a socket that block connection to a set of IP address 045 * @param pattern a regex to match against IP address (v4 or v6). Any address that matches the regex will be block. 046 * @param proxy the kind of proxy to use 047 */ 048 public IPRestrictedSocket(Pattern pattern, Proxy proxy) 049 { 050 super(proxy); 051 _pattern = pattern; 052 } 053 054 @Override 055 public void connect(SocketAddress endpoint, int timeout) throws IOException 056 { 057 if (endpoint instanceof InetSocketAddress epoint) 058 { 059 if (!_isRestricted(epoint.getAddress())) 060 { 061 super.connect(endpoint, timeout); 062 return; 063 } 064 else 065 { 066 throw new IPRestrictedException(epoint.getAddress()); 067 } 068 } 069 070 throw new IllegalStateException("Only InetSocketAddress are supported"); 071 } 072 073 private boolean _isRestricted(InetAddress address) 074 { 075 return _pattern.matcher(address.getHostAddress()).matches(); 076 } 077 078 /** 079 * Exception indicating that the connection to host was refused due to security restriction set on the client 080 */ 081 // Extends NoRouteToHost to avoid retry (see DefaultHttpRequestRetryStrategy) 082 public static class IPRestrictedException extends NoRouteToHostException 083 { 084 /** 085 * Build an exception for the given address 086 * @param address the restricted address 087 */ 088 public IPRestrictedException(InetAddress address) 089 { 090 super("Connection to " + address + " is restricted in Ametys security configuration"); 091 } 092 } 093}