OPC 서버는 안전합니까?

5657 단어
위에서 쓴 것은 클라이언트의 응용인데, 이번에는 서버의 안전성에 대해 이야기한다.COM 기반 OPC 서버를 쓰려면 일반적으로 실행 인터페이스를 정의해야 합니다. (OpcDa30Server.idl에서 발췌)
[
    uuid(ED0E3ADE-0CF5-47cd-A1AB-522E5E75D5CD),
    helpstring("OPC Data Access 3.00 Source Server")
]
coclass OpcDa30Server
{
    [default] interface IOPCServer;
    [source]  interface IOPCShutdown;
};

만약 네가 기초를 하나 쓰려고 한다면.NET의 OPC 서버는 일반적으로 OPC 기금회의 1.06판 SDK를 사용하는데 가장 일반적인 것은 다음과 같은 정의이다(Opc.IServer.cs에서 발췌).
public interface IServer : IDisposable	
{
    event ServerShutdownEventHandler ServerShutdown;
    string GetLocale();
    string SetLocale(string locale);
    string[] GetSupportedLocales();
    string GetErrorText(string locale, ResultID resultID);
}

자세한 서버 정의는 다음과 같습니다(Opc.Da.IServer.cs에서 발췌).
public interface IServer : Opc.IServer
{
    int GetResultFilters();	
    void SetResultFilters(int filters);
    ServerStatus GetStatus();
    ItemValueResult[] Read(Item[] items);
    IdentifiedResult[] Write(ItemValue[] values);
    ISubscription CreateSubscription(SubscriptionState state);
    void CancelSubscription(ISubscription subscription);
    BrowseElement[] Browse(ItemIdentifier itemID, BrowseFilters filters, out BrowsePosition position);
    BrowseElement[] BrowseNext(ref BrowsePosition position);
    ItemPropertyCollection[] GetProperties(ItemIdentifier[] itemIDs,PropertyID[] propertyIDs, bool returnValues);
}

여기를 보면 관리의 머릿속에서 이런 정의가 무슨 잘못이냐고 물어볼 수도 있다.어디가 안전하지 않습니까?
정답은 depends입니다.마이크로소프트 시스템에 설치된 OPC 서버와 마이크로소프트의 네트워크를 사용하는 데 마이크로소프트의 도메인 이름 계정(예를 들어 corp\user)을 사용한다.만약 당신의 도메인 계정이 함락되지 않았다면 OPC 서버는 안전합니다. 함락되면 하하.2015년 잠자리 공작 공격 사건 기억나세요?이는 물웅덩이 공격으로 공작 제어망에 사용되는 도메인 이름과 비밀번호를 얻어 마이크로소프트 네트워크에서 OPC 서버를 샅샅이 훑어보고 OPC의 인터페이스를 호출하여 해당하는 정보를 얻어 마음대로 읽을 수 있게 하는 것이다.이러한 OPC 서버는 안전합니까?아니죠.정해가 있습니까?
사실 OPC기금회는 안전에 관한 인터페이스를 내놓았지만 모두가 실행하지 않아 마이크로소프트의 네트워크를 사용하고 있다는 위험이 적다고 느꼈다.관련 COM 인터페이스는 다음과 같습니다(OpcSec.idl에서 발췌).
[
    object,
    uuid(7AA83A02-6C77-11d3-84F9-00008630A38B),
    pointer_default(unique)
]
interface IOPCSecurityPrivate : IUnknown
{
    HRESULT IsAvailablePriv([out] BOOL* pbAvailable);
    HRESULT Logon([in, string] LPCWSTR szUserID, [in, string] LPCWSTR szPassword);
    HRESULT Logoff(void);
};

C#의 적절한 인터페이스(Security.cs에서 발췌),
[ComImport]
[GuidAttribute("7AA83A02-6C77-11d3-84F9-00008630A38B")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IOPCSecurityPrivate
{
        void IsAvailablePriv([Out][MarshalAs(UnmanagedType.I4)] out int Available);
        void Logon([MarshalAs(UnmanagedType.LPWStr)] string szUserID,         
                   [MarshalAs(UnmanagedType.LPWStr)] string szPassword);
        void Logoff();
};

OPC 기금회가 가능한 안전 문제를 예견하고 자신의 답을 제시한 것을 알 수 있다.문제는 당신의 OPC 서버에서 실행되었습니까?OPC를 포함한 자신의 샘플 서버 프로그램은 보안 인터페이스를 실행하지 않았고, SDK를 기반으로 하는 2차 개발상들은 말할 나위도 없었다.
그럼 어떻게 구제합니까?위의 COM에서 정의한 클래스에 IOPCSecurityPrivate를 추가하여
[
    uuid(ED0E3ADE-0CF5-47cd-A1AB-522E5E75D5CD),
    helpstring("OPC Data Access 3.00 Source Server")
]
coclass OpcDa30Server
{
    [default] interface IOPCServer;
    [source]  interface IOPCShutdown;
    interface IOPCSecurityPrivate;
};

IOPC Security Private 아래의 Logon을 실행할 때 기금회가 제시한 견본은 다음과 같다(COPC Common.cpp에서 발췌).물론 그중의 m_를cUserName을 창의 보안 인식으로 바꿉니다(예: DWORD dwUserSecurityID를 정의한 다음 창에 해당하는 ID API를 호출하여 되돌아오는 dwUserSecurityID를 얻습니다).
HRESULT COpcCommon::Logon(LPCWSTR szUserID, LPCWSTR szPassword)
{
	if (szUserID == NULL || szUserID[0] == 0)
	{
		m_cUserName.Empty();
		return S_OK;
	}

	if (szPassword == NULL || szPassword[0] == 0)
	{
		return E_FAIL;
	}

	m_cUserName = szUserID;
	return S_OK;
}

이렇게 하면 IOPCServer의 AddGroup() 함수를 실행할 때 신분에 대한 검사(COPcDaServer.cpp에서 발췌)를 추가합니다. 일치하지 않으면 바로 다음과 같이 되돌려줍니다.
HRESULT COpcDaServer::AddGroup(LPCWSTR szName, BOOL bActive,DWORD dwRequestedUpdateRate, OPCHANDLE hClientGroup, LONG* pTimeBias, FLOAT*    pPercentDeadband, DWORD dwLCID, OPCHANDLE* phServerGroup, DWORD*   pRevisedUpdateRate, REFIID riid, LPUNKNOWN* ppUnk)
{
    if (m_cUserName.IsEmpty())
        return;

    COpcLock cLock(*this);

    COpcDaGroup* pGroup = NULL;

C#에서(Opc.Da.Server.cs에서 발췌), OpcRcw까지.Security.IOPCSecurityPrivate와 인터페이스 함수, 그리고 AddGroup () 같은 다른 인터페이스가 호출될 때 위와 같은 처리를 할 수 있습니다. (예를 들어 m_cUserName 또는 dwUserSecurityID 같은 변수를 정의하고 값을 검사합니다. 비어 있으면 바로 되돌아오기)
public class  Server : Opc.Da.IServer, OpcRcw.Security.IOPCSecurityPrivate
    {
        #region OpcRcw.Security.IOPCSecurityPrivate
        public void IsAvailablePriv([MarshalAs(UnmanagedType.I4), Out] out int pbAvailable) {
            /*   m_cUserName   dwUserSecurityID  */
        }

        public void Logon([MarshalAs(UnmanagedType.LPWStr)] string szUserID, [MarshalAs(UnmanagedType.LPWStr)] string szPassword) {
            /*   m_cUserName   dwUserSecurityID */
        }

        public void Logoff() {
            /*   m_cUserName   dwUserSecurityID*/
        }
        #endregion

요약하면 만약에 사용자가 마이크로소프트 도메인 아래의 계정을 사용한다면 사용자 계정이 함락된 상황에서 OPC 서버의 안전을 확보하기 위해 독립적으로 OPC 서버에 로그인하여 사용할 수 있는 계정을 창설해야 하며 이 계정은 다른 용도로 사용되지 않는다.OPC 서버에 요청을 보낼 때 클라이언트가 사용하는 첫 번째 OPC 인터페이스는 Logon () 이고 OPC 서버와 그 뒤에 해당하는 인터페이스 호출을 찾아야 합니다.위의 OPC 서버 자체의 보안 특성을 제외하고 DCOM과 같은 설정에서도 보안 측면의 경화를 할 수 있습니다. 여기서 더 이상 설명하지 않겠습니다.일부 시청자는 내가 이미 제3자의 OPC 서버가 실행되고 Logon () 인터페이스를 사용하지 않았는데 이런 상황은 어떻게 합니까?이런 상황은 비교적 복잡하다. 만약 여러분이 흥미를 느끼신다면 나중에 OPC 패키지의 깊이 있는 해석과 공업 방화벽 아래에서 응용에 관한 박문을 한 편 더 쓰겠습니다. 메시지를 남겨주세요!
본인의 다음 편은 여기 있습니다.

좋은 웹페이지 즐겨찾기