forum.bitel.ru http://forum.bitel.ru/ |
|
Создание сессии или подключения только по Access-Request http://forum.bitel.ru/viewtopic.php?f=44&t=11484 |
Страница 1 из 1 |
Автор: | vdd [ 30 мар 2016, 16:59 ] |
Заголовок сообщения: | Создание сессии или подключения только по Access-Request |
Есть оборудование, отсылающее только RADIUS Access-Request и Netflow. IP адрес также выделяется оборудованием и присылается в Access-Request. Поиск сервиса осуществляется по User-Name. Можно ли в обработчике радиус-протокола, или каким-либо другим способом создать сессию или подключение для того, что бы Netflow трафик привязался к сервису? Проверены варианты: 1. connection.start.fromAccept=1 Результат: запись в таблице inet_connection создается с пустым ipAddress , netflow трафик не привязывается, не создает сессии. 2. Отправлять Accounting с помощью RadiusClienta из обработчика протокола для штатной процедуры создания сессии. Результат: утечка ресурсов в BGInetAccess (https://forum.bitel.ru/viewtopic.php?f=44&t=11480) Известны варианты: 1. Забить на радиус. - Не хотелось бы, так как другие варианты управления хуже. 2. Создать имитатор полноценного радиус-клиента. - Можно, но "бритва Оккама" душит. |
Автор: | Amir [ 30 мар 2016, 19:08 ] |
Заголовок сообщения: | Re: Создание сессии или подключения только по Access-Request |
Можно попробовать попросить стартовать сессию InetAccounting, т.к. как это примерно делается при работе DHCP-сервера: Код: import java.util.Date; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.annotation.Resource; import javax.naming.NameNotFoundException; import org.apache.log4j.Logger; import ru.bitel.bgbilling.kernel.container.managed.ServerContext; import ru.bitel.bgbilling.kernel.container.resource.ResourceManager; import ru.bitel.bgbilling.kernel.network.dhcp.DhcpProtocolHandler; import ru.bitel.bgbilling.kernel.network.radius.RadiusAttributeSet; import ru.bitel.bgbilling.kernel.network.radius.RadiusDictionary; import ru.bitel.bgbilling.kernel.network.radius.RadiusListenerWorker; import ru.bitel.bgbilling.kernel.network.radius.RadiusPacket; import ru.bitel.bgbilling.kernel.network.radius.RadiusProtocolHandler; import ru.bitel.bgbilling.kernel.network.radius.RadiusSession; import ru.bitel.bgbilling.modules.inet.access.Access; import ru.bitel.bgbilling.modules.inet.access.sa.ProtocolHandlerAdapter; import ru.bitel.bgbilling.modules.inet.api.common.AccessCodes; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetConnection; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDevice; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDeviceType; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetServ; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetServType; import ru.bitel.bgbilling.modules.inet.radius.InetNas; import ru.bitel.bgbilling.modules.inet.radius.InetRadiusSessionParams; import ru.bitel.bgbilling.modules.inet.radius.RadiusAccessRequestHandler; import ru.bitel.bgbilling.server.util.Setup; import ru.bitel.common.ParameterMap; import ru.bitel.common.function.ThrowingRunnable; public class MyProtocolHandler extends ProtocolHandlerAdapter implements RadiusProtocolHandler, DhcpProtocolHandler, RadiusAccessRequestHandler { private static final Logger logger = Logger.getLogger( MyProtocolHandler.class ); private static final ExecutorService executor = Executors.newFixedThreadPool( 10 ); @Resource(name = "access") private Access access; private int deviceId; @Override public void init( Setup setup, int moduleId, InetDevice inetDevice, InetDeviceType inetDeviceType, ParameterMap deviceConfig ) throws Exception { super.init( setup, moduleId, inetDevice, inetDeviceType, deviceConfig ); this.deviceId = inetDevice.getId(); ServerContext ctx = new ServerContext( setup, moduleId, 0 ); ctx.init(); try { ResourceManager rm = new ResourceManager(); rm.inject( ctx, this, moduleId ); ctx.commit(); } catch( NameNotFoundException ex ) {} catch( Exception ex ) { logger.error( ex.getMessage(), ex ); } finally { ctx.destroy(); } } @Override public void beforeAuthentication( ServerContext context, RadiusListenerWorker<InetNas> req, RadiusSession<InetNas, InetRadiusSessionParams> radiusSession, RadiusPacket request, RadiusPacket response ) throws Exception {} @Override public boolean addResponseAttributes( ServerContext context, InetServType inetServType, InetServ inetServ, RadiusPacket response, String realm, Map<String, RadiusAttributeSet> realmAttributeMap, RadiusAttributeSet inetServAttributes, Set<Integer> inetOptionSet ) throws Exception { return false; } @Override public void afterAuthorization( ServerContext conext, RadiusListenerWorker<InetNas> req, RadiusSession<InetNas, InetRadiusSessionParams> radiusSession, RadiusPacket request, RadiusPacket response ) throws Exception { if( response.getCode() != RadiusPacket.ACCESS_ACCEPT ) { return; } int accessCode = radiusSession.errorCode; InetServ serv = (InetServ)req.getRadiusSession().login; InetConnection connection = new InetConnection(); connection.setDeviceId( deviceId ); connection.setDevicePort( serv.getInterfaceId() ); connection.setCircuitId( req.getCircuitId() ); connection.setContractId( req.getContractId() ); connection.setServId( serv.getId() ); connection.setAcctSessionId( request.getStringAttribute( -1, RadiusDictionary.Acct_Session_Id, "UNDEF" ) ); connection.setCallingStationId( request.getStringAttribute( -1, RadiusDictionary.Calling_Station_Id, "" ) ); connection.setIpResourceId( req.getIpResourceId() ); connection.setInetAddressBytes( req.getIpAddress() ); connection.setAccessCode( accessCode ); connection.setDeviceState( (accessCode != AccessCodes.AUTHORIZATION_SUCCEEDED) ? InetServ.STATE_DISABLE : InetServ.STATE_ENABLE ); connection.setConnectionStart( new Date() ); executor.execute( (ThrowingRunnable)() -> { access.connectionManager.accountingStart( serv, connection, 4000 ); } ); } } |
Автор: | Amir [ 30 мар 2016, 19:13 ] |
Заголовок сообщения: | Re: Создание сессии или подключения только по Access-Request |
В данном случае обработчику процессора протокола я добавил implements RadiusAccessRequestHandler и теперь можно использовать дополнительные три метода. Использую afterAuthorization во-первых, потому что там доступно больше данных, во-вторых, потому что preprocess/postprocessRequest в случае EAP может вызываться несколько раз до того как произойдет Access-Accept. executor.execute использую, чтобы сам старт выполнялся асинхронно уже в другом потоке (чтобы не дожидаясь создания сессии отправить Access-Accept). Это пример, не факт что сразу заработает, но в принципе так должно работать тоже. |
Автор: | vdd [ 30 мар 2016, 19:53 ] |
Заголовок сообщения: | Re: Создание сессии или подключения только по Access-Request |
Понял, спасибо. Не получится стабильного решения с автоАккоунтингом - попробую этот вариант. |
Страница 1 из 1 | Часовой пояс: UTC + 5 часов [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |