VirtualBox

Changeset 94521 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Apr 7, 2022 3:18:48 PM (3 years ago)
Author:
vboxsync
Message:

libs/libssh,Main,FE/VBoxManage,Devices/Network/DrvCloudTunnel|ai: Add support for proxies, bugref:9469

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DrvCloudTunnel.cpp

    r93394 r94521  
    8787    /** SSH connection timeout in seconds. */
    8888    long                    ulTimeoutInSecounds;
     89
     90    /** Primary proxy type. */
     91    char                    *pszPrimaryProxyType;
     92    /** Primary proxy server IP address. */
     93    char                    *pszPrimaryProxyHost;
     94    /** Primary proxy server port. */
     95    uint16_t                u16PrimaryProxyPort;
     96    /** Primary proxy user. */
     97    char                    *pszPrimaryProxyUser;
     98    /** Primary proxy password. */
     99    char                    *pszPrimaryProxyPassword;
     100
     101    /** Secondary proxy type. */
     102    char                    *pszSecondaryProxyType;
     103    /** Secondary proxy server IP address. */
     104    char                    *pszSecondaryProxyHost;
     105    /** Secondary proxy server port. */
     106    uint16_t                u16SecondaryProxyPort;
     107    /** Secondary proxy user. */
     108    char                    *pszSecondaryProxyUser;
     109    /** Secondary proxy password. */
     110    char                    *pszSecondaryProxyPassword;
     111
    89112    /** Cloud tunnel instance string. */
    90113    char                    *pszInstance;
     
    10251048        rc = drvCloudTunnelExecuteRemoteCommand(pThis, "sudo ip link set dev %s address %RTmac", pThis->pszCloudPrimaryInterface, pThis->targetMac.au8);
    10261049    if (RT_SUCCESS(rc))
     1050        rc = drvCloudTunnelExecuteRemoteCommand(pThis, "sudo ifconfig %s 0.0.0.0", pThis->pszCloudPrimaryInterface); /* Make sure no IP is configured on primary */
     1051    if (RT_SUCCESS(rc))
    10271052        rc = drvCloudTunnelExecuteRemoteCommand(pThis, "sudo ip link set dev %s master br0", pThis->pszCloudPrimaryInterface);
    10281053    if (RT_SUCCESS(rc))
     
    11271152
    11281153
    1129 static int drvCloudTunnelSwitchToSecondary(PDRVCLOUDTUNNEL pThis)
     1154static int drvCloudTunnelNewSession(PDRVCLOUDTUNNEL pThis, bool fPrimary)
    11301155{
    11311156    pThis->pSshSession = ssh_new();
     
    11391164        return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    11401165                                   N_("Failed to set SSH_OPTIONS_USER"));
    1141     if (ssh_options_set(pThis->pSshSession, SSH_OPTIONS_HOST, pThis->pszPrimaryIP) < 0)
     1166    if (ssh_options_set(pThis->pSshSession, SSH_OPTIONS_HOST, fPrimary ? pThis->pszPrimaryIP : pThis->pszSecondaryIP) < 0)
    11421167        return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    11431168                                   N_("Failed to set SSH_OPTIONS_HOST"));
     
    11471172                                   N_("Failed to set SSH_OPTIONS_TIMEOUT"));
    11481173
     1174    const char *pcszProxyType = fPrimary ? pThis->pszPrimaryProxyType : pThis->pszSecondaryProxyType;
     1175    if (pcszProxyType)
     1176    {
     1177        char szProxyCmd[1024];
     1178
     1179        const char *pcszProxyUser = fPrimary ? pThis->pszPrimaryProxyUser : pThis->pszSecondaryProxyUser;
     1180        if (pcszProxyUser)
     1181            RTStrPrintf(szProxyCmd, sizeof(szProxyCmd), "#VBoxProxy%s %s %u %s %s",
     1182                        fPrimary ? pThis->pszPrimaryProxyType : pThis->pszSecondaryProxyType,
     1183                        fPrimary ? pThis->pszPrimaryProxyHost : pThis->pszSecondaryProxyHost,
     1184                        fPrimary ? pThis->u16PrimaryProxyPort : pThis->u16SecondaryProxyPort,
     1185                        fPrimary ? pThis->pszPrimaryProxyUser : pThis->pszSecondaryProxyUser,
     1186                        fPrimary ? pThis->pszPrimaryProxyPassword : pThis->pszSecondaryProxyPassword);
     1187        else
     1188            RTStrPrintf(szProxyCmd, sizeof(szProxyCmd), "#VBoxProxy%s %s %u",
     1189                        fPrimary ? pThis->pszPrimaryProxyType : pThis->pszSecondaryProxyType,
     1190                        fPrimary ? pThis->pszPrimaryProxyHost : pThis->pszSecondaryProxyHost,
     1191                        fPrimary ? pThis->u16PrimaryProxyPort : pThis->u16SecondaryProxyPort);
     1192        LogRel(("%s: using proxy command '%s'\n", pThis->pszInstance, szProxyCmd));
     1193        if (ssh_options_set(pThis->pSshSession, SSH_OPTIONS_PROXYCOMMAND, szProxyCmd) < 0)
     1194            return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
     1195                                    N_("Failed to set SSH_OPTIONS_PROXYCOMMAND"));
     1196    }
     1197
    11491198    int rc = ssh_connect(pThis->pSshSession);
    1150     if (rc != SSH_OK)
     1199    for (int cAttempt = 1; rc != SSH_OK && cAttempt <= 5; cAttempt++)
    11511200    {
    11521201        ssh_disconnect(pThis->pSshSession);
    11531202        /* One more time, just to be sure. */
    1154         LogRel(("%s: failed to connect to %s, retrying...\n", pThis->pszInstance, pThis->pszPrimaryIP));
     1203        LogRel(("%s: failed to connect to %s, retrying(#%d)...\n", pThis->pszInstance,
     1204                fPrimary ? pThis->pszPrimaryIP : pThis->pszSecondaryIP, cAttempt));
     1205        RTThreadSleep(10000); /* Sleep 10 seconds, then retry */
    11551206        rc = ssh_connect(pThis->pSshSession);
    11561207    }
    11571208    if (rc != SSH_OK)
    11581209        return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1159                                    N_("CloudTunnel: Failed to connect to primary interface"));
     1210                                   N_("CloudTunnel: Failed to connect to %s interface"), fPrimary ? "primary" : "secondary");
    11601211
    11611212    rc = ssh_userauth_publickey(pThis->pSshSession, NULL, pThis->SshKey);
     
    11641215                                   N_("Failed to authenticate with public key"));
    11651216
     1217    return VINF_SUCCESS;
     1218}
     1219
     1220static int drvCloudTunnelSwitchToSecondary(PDRVCLOUDTUNNEL pThis)
     1221{
     1222    int rc = drvCloudTunnelNewSession(pThis, true /* fPrimary */);
    11661223    /*
    11671224     * Establish temporary console channel and configure the cloud instance
    11681225     * to bridge the tunnel channel to instance's primary interface.
    11691226     */
    1170     rc = drvCloudTunnelCloudInstanceInitialConfig(pThis);
     1227    if (RT_SUCCESS(rc))
     1228        rc = drvCloudTunnelCloudInstanceInitialConfig(pThis);
    11711229
    11721230    ssh_disconnect(pThis->pSshSession);
     
    11801238static int establishTunnel(PDRVCLOUDTUNNEL pThis)
    11811239{
    1182     pThis->pSshSession = ssh_new();
    1183     if (pThis->pSshSession == NULL)
    1184         return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1185                                    N_("CloudTunnel: Failed to allocate new SSH session"));
    1186     if (ssh_options_set(pThis->pSshSession, SSH_OPTIONS_LOG_VERBOSITY, &pThis->iSshVerbosity) < 0)
    1187         return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1188                                    N_("Failed to set SSH_OPTIONS_LOG_VERBOSITY"));
    1189     if (ssh_options_set(pThis->pSshSession, SSH_OPTIONS_USER, pThis->pszUser) < 0)
    1190         return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1191                                    N_("Failed to set SSH_OPTIONS_USER"));
    1192     if (ssh_options_set(pThis->pSshSession, SSH_OPTIONS_HOST, pThis->pszSecondaryIP) < 0)
    1193         return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1194                                    N_("Failed to set SSH_OPTIONS_HOST"));
    1195 
    1196     if (ssh_options_set(pThis->pSshSession, SSH_OPTIONS_TIMEOUT, &pThis->ulTimeoutInSecounds) < 0)
    1197         return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1198                                    N_("Failed to set SSH_OPTIONS_TIMEOUT"));
    1199 
    1200     int rc = ssh_connect(pThis->pSshSession);
    1201     if (rc != SSH_OK)
    1202     {
    1203         ssh_disconnect(pThis->pSshSession);
    1204         /* One more time, just to be sure. */
    1205         Log(("%s: failed to connect to %s, retrying...\n", pThis->pszInstance, pThis->pszSecondaryIP));
    1206         rc = ssh_connect(pThis->pSshSession);
    1207     }
    1208     if (rc != SSH_OK)
    1209         return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1210                                    N_("CloudTunnel: Failed to connect to secondary interface"));
    1211 
    1212     rc = ssh_userauth_publickey(pThis->pSshSession, NULL, pThis->SshKey);
    1213     if (rc != SSH_AUTH_SUCCESS)
    1214         return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
    1215                                    N_("Failed to authenticate with public key"));
    1216 
    1217     rc = drvCloudTunnelCloudInstanceFinalConfig(pThis);
     1240    int rc = drvCloudTunnelNewSession(pThis, false /* fPrimary */);
     1241    if (RT_SUCCESS(rc))
     1242        rc = drvCloudTunnelCloudInstanceFinalConfig(pThis);
    12181243    if (RT_SUCCESS(rc))
    12191244        rc = drvCloudTunnelOpenTunnelChannel(pThis);
     
    12621287/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
    12631288
     1289DECLINLINE(void) drvCloudTunnelStrFree(char **ppszString)
     1290{
     1291    if (*ppszString)
     1292    {
     1293        RTStrFree(*ppszString);
     1294        *ppszString = NULL;
     1295    }
     1296}
     1297
     1298DECLINLINE(void) drvCloudTunnelHeapFree(PPDMDRVINS pDrvIns, char **ppszString)
     1299{
     1300    if (*ppszString)
     1301    {
     1302        PDMDrvHlpMMHeapFree(pDrvIns, *ppszString);
     1303        *ppszString = NULL;
     1304    }
     1305}
     1306
    12641307/**
    12651308 * Destruct a driver instance.
     
    12861329    }
    12871330
    1288     if (pThis->pszCloudPrimaryInterface)
    1289     {
    1290         RTStrFree(pThis->pszCloudPrimaryInterface);
    1291         pThis->pszCloudPrimaryInterface = NULL;
    1292     }
    1293 
    1294     if (pThis->pszSecondaryIP)
    1295     {
    1296         RTStrFree(pThis->pszSecondaryIP);
    1297         pThis->pszSecondaryIP = NULL;
    1298     }
    1299 
    1300     if (pThis->pszPrimaryIP)
    1301     {
    1302         RTStrFree(pThis->pszPrimaryIP);
    1303         pThis->pszPrimaryIP = NULL;
    1304     }
    1305 
    1306     if (pThis->pszUser)
    1307     {
    1308         RTStrFree(pThis->pszUser);
    1309         pThis->pszUser = NULL;
    1310     }
    1311 
    1312     if (pThis->pszInstanceDev)
    1313     {
    1314         RTStrFree(pThis->pszInstanceDev);
    1315         pThis->pszInstanceDev = NULL;
    1316     }
    1317 
    1318     if (pThis->pszInstanceIo)
    1319     {
    1320         RTStrFree(pThis->pszInstanceIo);
    1321         pThis->pszInstanceIo = NULL;
    1322     }
    1323 
    1324     if (pThis->pszInstance)
    1325     {
    1326         RTStrFree(pThis->pszInstance);
    1327         pThis->pszInstance = NULL;
    1328     }
    1329 
    1330     if (pThis->pszOutputBuffer)
    1331     {
    1332         RTStrFree(pThis->pszOutputBuffer);
    1333         pThis->pszOutputBuffer = NULL;
    1334     }
    1335 
    1336     if (pThis->pszCommandBuffer)
    1337     {
    1338         RTStrFree(pThis->pszCommandBuffer);
    1339         pThis->pszCommandBuffer = NULL;
    1340     }
     1331    drvCloudTunnelStrFree(&pThis->pszCloudPrimaryInterface);
     1332
     1333    drvCloudTunnelHeapFree(pDrvIns, &pThis->pszPrimaryProxyType);
     1334    drvCloudTunnelStrFree(&pThis->pszPrimaryProxyHost);
     1335    drvCloudTunnelHeapFree(pDrvIns, &pThis->pszPrimaryProxyUser);
     1336    drvCloudTunnelStrFree(&pThis->pszPrimaryProxyPassword);
     1337
     1338    drvCloudTunnelHeapFree(pDrvIns, &pThis->pszSecondaryProxyType);
     1339    drvCloudTunnelStrFree(&pThis->pszSecondaryProxyHost);
     1340    drvCloudTunnelHeapFree(pDrvIns, &pThis->pszSecondaryProxyUser);
     1341    drvCloudTunnelStrFree(&pThis->pszSecondaryProxyPassword);
     1342
     1343    drvCloudTunnelStrFree(&pThis->pszSecondaryIP);
     1344    drvCloudTunnelStrFree(&pThis->pszPrimaryIP);
     1345    drvCloudTunnelStrFree(&pThis->pszUser);
     1346
     1347    drvCloudTunnelStrFree(&pThis->pszInstanceDev);
     1348    drvCloudTunnelStrFree(&pThis->pszInstanceIo);
     1349    drvCloudTunnelStrFree(&pThis->pszInstance);
     1350
     1351    drvCloudTunnelStrFree(&pThis->pszOutputBuffer);
     1352    drvCloudTunnelStrFree(&pThis->pszCommandBuffer);
    13411353
    13421354    ssh_key_free(pThis->SshKey);
     
    14421454                                            "|PrimaryIP"
    14431455                                            "|SecondaryIP"
    1444                                             "|TargetMAC",
    1445                                             "");
     1456                                            "|TargetMAC"
     1457
     1458                                            "|PrimaryProxyType"
     1459                                            "|PrimaryProxyHost"
     1460                                            "|PrimaryProxyPort"
     1461                                            "|PrimaryProxyUser"
     1462                                            "|PrimaryProxyPassword"
     1463                                            "|SecondaryProxyType"
     1464                                            "|SecondaryProxyHost"
     1465                                            "|SecondaryProxyPort"
     1466                                            "|SecondaryProxyUser"
     1467                                            "|SecondaryProxyPassword"
     1468
     1469                                            ,"");
    14461470
    14471471    /*
     
    15131537        return PDMDRV_SET_ERROR(pDrvIns, VERR_INVALID_BASE64_ENCODING,
    15141538                                N_("DrvCloudTunnel: Configuration error: Converting \"SshKey\" from base64 failed"));
     1539
     1540    /* PrimaryProxyType is optional */
     1541    rc = pHlp->pfnCFGMQueryStringAllocDef(pCfg, "PrimaryProxyType", &pThis->pszPrimaryProxyType, NULL);
     1542    if (RT_FAILURE(rc))
     1543        return PDMDRV_SET_ERROR(pDrvIns, rc,
     1544                                N_("DrvCloudTunnel: Configuration error: Querying \"PrimaryProxyType\" as string failed"));
     1545    if (pThis->pszPrimaryProxyType)
     1546    {
     1547        rc = pHlp->pfnCFGMQueryString(pCfg, "PrimaryProxyHost", szVal, sizeof(szVal));
     1548        if (RT_FAILURE(rc))
     1549            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1550                                    N_("DrvCloudTunnel: Configuration error: Querying \"PrimaryProxyHost\" as string failed"));
     1551        rc = RTNetStrToIPv4Addr(szVal, &tmpAddr);
     1552        if (RT_FAILURE(rc))
     1553            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1554                                    N_("DrvCloudTunnel: Configuration error: \"PrimaryProxyHost\" is not valid"));
     1555        else
     1556            pThis->pszPrimaryProxyHost = RTStrDup(szVal);
     1557
     1558        uint64_t u64Val;
     1559        rc = pHlp->pfnCFGMQueryInteger(pCfg, "PrimaryProxyPort", &u64Val);
     1560        if (RT_FAILURE(rc))
     1561            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1562                                    N_("DrvCloudTunnel: Configuration error: Querying \"PrimaryProxyPort\" as integer failed"));
     1563        if (u64Val > 0xFFFF)
     1564            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1565                                    N_("DrvCloudTunnel: Configuration error: \"PrimaryProxyPort\" is not valid"));
     1566        pThis->u16PrimaryProxyPort = (uint16_t)u64Val;
     1567
     1568        /* PrimaryProxyUser is optional */
     1569        rc = pHlp->pfnCFGMQueryStringAllocDef(pCfg, "PrimaryProxyUser", &pThis->pszPrimaryProxyUser, NULL);
     1570        if (RT_FAILURE(rc))
     1571            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1572                                    N_("DrvCloudTunnel: Configuration error: Querying \"PrimaryProxyUser\" as string failed"));
     1573        /* PrimaryProxyPassword must be present if PrimaryProxyUser is present */
     1574        if (pThis->pszPrimaryProxyUser)
     1575        {
     1576            rc = pHlp->pfnCFGMQueryPassword(pCfg, "PrimaryProxyPassword", szVal, sizeof(szVal));
     1577            if (RT_FAILURE(rc))
     1578                return PDMDRV_SET_ERROR(pDrvIns, rc,
     1579                                        N_("DrvCloudTunnel: Configuration error: Querying \"PrimaryProxyPassword\" as string failed"));
     1580            pThis->pszPrimaryProxyPassword = RTStrDup(szVal);
     1581        }
     1582    }
     1583
     1584    /* SecondaryProxyType is optional */
     1585    rc = pHlp->pfnCFGMQueryStringAllocDef(pCfg, "SecondaryProxyType", &pThis->pszSecondaryProxyType, NULL);
     1586    if (RT_FAILURE(rc))
     1587        return PDMDRV_SET_ERROR(pDrvIns, rc,
     1588                                N_("DrvCloudTunnel: Configuration error: Querying \"SecondaryProxyType\" as string failed"));
     1589    if (pThis->pszSecondaryProxyType)
     1590    {
     1591        if (RT_FAILURE(rc))
     1592            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1593                                    N_("DrvCloudTunnel: Configuration error: Querying \"SecondaryProxyType\" as string failed"));
     1594
     1595        rc = pHlp->pfnCFGMQueryString(pCfg, "SecondaryProxyHost", szVal, sizeof(szVal));
     1596        if (RT_FAILURE(rc))
     1597            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1598                                    N_("DrvCloudTunnel: Configuration error: Querying \"SecondaryProxyHost\" as string failed"));
     1599        rc = RTNetStrToIPv4Addr(szVal, &tmpAddr);
     1600        if (RT_FAILURE(rc))
     1601            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1602                                    N_("DrvCloudTunnel: Configuration error: \"SecondaryProxyHost\" is not valid"));
     1603        else
     1604            pThis->pszSecondaryProxyHost = RTStrDup(szVal);
     1605
     1606        uint64_t u64Val;
     1607        rc = pHlp->pfnCFGMQueryInteger(pCfg, "SecondaryProxyPort", &u64Val);
     1608        if (RT_FAILURE(rc))
     1609            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1610                                    N_("DrvCloudTunnel: Configuration error: Querying \"SecondaryProxyPort\" as integer failed"));
     1611        if (u64Val > 0xFFFF)
     1612            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1613                                    N_("DrvCloudTunnel: Configuration error: \"SecondaryProxyPort\" is not valid"));
     1614        pThis->u16SecondaryProxyPort = (uint16_t)u64Val;
     1615
     1616        /* SecondaryProxyUser is optional */
     1617        rc = pHlp->pfnCFGMQueryStringAllocDef(pCfg, "SecondaryProxyUser", &pThis->pszSecondaryProxyUser, NULL);
     1618        if (RT_FAILURE(rc))
     1619            return PDMDRV_SET_ERROR(pDrvIns, rc,
     1620                                    N_("DrvCloudTunnel: Configuration error: Querying \"SecondaryProxyUser\" as string failed"));
     1621        /* SecondaryProxyPassword must be present if SecondaryProxyUser is present */
     1622        if (pThis->pszSecondaryProxyUser)
     1623        {
     1624            rc = pHlp->pfnCFGMQueryPassword(pCfg, "SecondaryProxyPassword", szVal, sizeof(szVal));
     1625            if (RT_FAILURE(rc))
     1626                return PDMDRV_SET_ERROR(pDrvIns, rc,
     1627                                        N_("DrvCloudTunnel: Configuration error: Querying \"SecondaryProxyPassword\" as string failed"));
     1628            pThis->pszSecondaryProxyPassword = RTStrDup(szVal);
     1629        }
     1630    }
    15151631
    15161632    pThis->pszCommandBuffer = (char *)RTMemAlloc(DRVCLOUDTUNNEL_COMMAND_BUFFER_SIZE);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette