Rafficer / linux-cli-community

Linux command-line client for ProtonVPN. Written in Python.
https://protonvpn.com
GNU General Public License v3.0
1.29k stars 194 forks source link

[BUG] "protonvpn s" doesn't work anymore #367

Open hertz0022 opened 5 months ago

hertz0022 commented 5 months ago

Hi, for one/two weeks now the status command doesn't work anymore. Latest v2.2.12-1, installed from AUR, Python v3.11.8. Here is its output:

ProtonVPN now offers an official Linux app which includes a graphical user interface. Visit https://protonvpn.com/support/official-linux-client to upgrade. Traceback (most recent call last): File "/sbin/protonvpn", line 33, in sys.exit(load_entry_point('protonvpn-cli==2.2.12', 'console_scripts', 'protonvpn')()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/site-packages/protonvpn_cli/cli.py", line 72, in main cli() File "/usr/lib/python3.11/site-packages/protonvpn_cli/cli.py", line 144, in cli connection.status() File "/usr/lib/python3.11/site-packages/protonvpn_cli/connection.py", line 444, in status

The rest seems to work as usually. Maybe a python update that broke something? Don't remember when I last updated it. Thanks, great client btw, always used it!

Expressive-Synapse commented 5 months ago

Im experiencing the same thing. Also using the latest version from the AUR.

hertz0022 commented 5 months ago

A detail I didn't mention is that if it's disconnected the command runs as expected. Only happens under a vpn connection.

marcel-engelke commented 5 months ago

It seems that the feature key does not match the hardcoded all_features map anymore.

connection.py:

    # Collect Information
    all_features = {0: "Normal", 1: "Secure-Core", 2: "Tor", 4: "P2P"}

    logger.debug("Collecting status information")
    country_code = get_server_value(connected_server, "ExitCountry", servers)
    country = get_country_name(country_code)
    city = get_server_value(connected_server, "City", servers)
    load = get_server_value(connected_server, "Load", servers)
    feature = get_server_value(connected_server, "Features", servers)
    last_connection = get_config_value("metadata", "connected_time")
    connection_time = time.time() - int(last_connection)

    if os.path.isfile(os.path.join(CONFIG_DIR, "iptables.backup")):
        killswitch_on = True
    else:
        killswitch_on = False
    killswitch_status = "Enabled" if killswitch_on else "Disabled"
    # Turn time into human readable format and trim microseconds
    connection_time = str(datetime.timedelta(
        seconds=connection_time)).split(".")[0]

    tx_amount, rx_amount = get_transferred_data()

    # Print Status Output
    logger.debug("Printing status")
    print(
        "Status:       Connected\n"
        + "Time:         {0}\n".format(connection_time)
        + "IP:           {0}\n".format(ip)
        + "Server:       {0}\n".format(connected_server)
        + "Features:     {0}\n".format(all_features[feature])
        + "Protocol:     {0}\n".format(connected_protocol.upper())
        + "Kill Switch:  {0}\n".format(killswitch_status)
        + "Country:      {0}\n".format(country)
        + "City:         {0}\n".format(city)
        + "Load:         {0}%\n".format(load)
        + "Received:     {0}\n".format(rx_amount)
        + "Sent:         {0}".format(tx_amount)
    )

I'll look further into this, I might be able to submit a fix

marcel-engelke commented 5 months ago

The VPN server features are stored as bitflags, but the CLI does not support decoding them, simply mapping every feature to a value instead. This causes the issue described above when a server supports multiple features.

After some digging, I found that the feature flags are defined in proton-vpn-session/servers/types.py

class ServerFeatureEnum(IntFlag):
    """
    A Class representing the Server features as encoded in the feature flags field of the API:
    """
    SECURE_CORE = 1 << 0  # 1
    TOR = 1 << 1  # 2
    P2P = 1 << 2  # 4
    STREAMING = 1 << 3  # 8
    IPV6 = 1 << 4  # 16

For example the 12 seen in KeyError: 12 would correspond to the server features P2P (4) + STREAMING (8).

I'm going to implement handling for this and submit a PR.