Inactive [WEB/DEV/ADMIN] HTTPConsole 0.3.0 - Issue Console Commands Over HTTP [803]

Discussion in 'Inactive/Unsupported Plugins' started by BlueJeansAndRain, Apr 11, 2011.

  1. HTTPConsole - Issue Console Commands Over HTTP
    Version: 0.3.0

    I wrote this because I have a bash script which I use to backup the worlds and do mapping and various other manipulations directly on world data. So, I needed a way for the script to tell the server to save-all, then disable saving to copy the worlds, then re-enable saving. I know there are plugins out there that expose a limited API over HTTP, and there's even one that provides telnet access. But the APIs didn't provide the access I wanted and telnet access is too cumbersome.

    While I was at it I figured I would make it capable of issuing any console command. You never know what you might need :).

    WARNING: If you configure this plugin to listen on an ip address open to the internet, and don't restrict client IP addresses (using the white and black lists) to specific IP addresses you trust, someone will hack your server.

    This is my first plugin... actually this is the first thing I've ever written in Java, so be gentle with my source :p. Suggestions welcome.

    Features:
    • Issue any command over HTTP that you can issue on the console.
    • Change the listener IP address, port, and log-level through the config file.
    • Get back the output of the issued command.
      • This only works for some commands, specifically commands that are not "threaded".
    • Accepts GET and POST (url or json encoded) requests.
    • Client IP address whitelist/blacklist.
    • Host name filtering.
    Trouble Shooting: If it doesn't appear to be working, try the following solutions.
    • Change the "port: 8765" configuration option to a different number. Valid values are 1024 - 65565
    • Make sure your firewall is allowing access to the port.
    Download the plugin Jar

    Source Code
    Usage (open)

    Make requests to http://127.0.0.1:8765/console?command=<command> (assuming you're using the default port and the server is running on localhost). If you're running your server locally, just open up your browser and type http://127.0.0.1:8765/console?command=save-all and SAVE THE WORLD!
    Default config.yml (open)

    Code:
    # The IP address that HTTPConsole will listen on. "any" can be used to listen on
    #  any address.
    # The default is 127.0.0.1
    ip-address: 127.0.0.1
    
    # The TCP listening port that HTTPConsole will bind to.
    # The default is 8765.
    port: 8765
    
    # Controls how important a console message must be to be shown.
    # Possible values: severe, warning, info
    # The default is severe, meaning only severe log messages will be visible.
    log-level: severe
    
    # Controls whether messages beginning with "ConsoleCommandSender:" are filtered
    #  out of the console log.
    # The default value is true.
    filter-command-sender: true
    
    # This sets what ip addresses are not allowed to send requests to HTTPConsole.
    # To add more values, just add more "- ipaddress" lines to the list.
    # Add "- any" (no quotes) to the list to block all ip addresses from connecting
    #  to HTTPConsole.
    # Ranges of ip addresses can be set by using two ip addresses seperated by a
    #  hyphen (-), or by using an asterisk (*) in place of any number.
    # Hyphens and asterisks are special characters in yml files so they will have
    #  to be surrounded by quotes (see examples below).
    client-ip-blacklist:
    #   - 192.168.3.2
    #   - "192.168.4.*"
    #   - "192.168.5.1-192.168.6.254"
    #   - any
    
    # This sets what ip addresses are allowed to send requests to HTTPConsole.
    # All ip addresses and ranges that are valid for the blacklist are also valid
    #  for the whitelist.
    client-ip-whitelist:
    #   Example:
    #   - 192.168.1.100
    #   - "192.168.2.*"
    #   - "192.168.0.1-192.168.0.254"
    #   - any
    
    # This changes the order in which the whitelist and blacklist are checked.
    # Possible Values:
    #
    #  "Deny,Allow"
    #   The whitelist is only checked when an ip address matches the blacklist.
    #   If the ip address matches both lists, it will be allowed. If it matches
    #    neither list, it will be allowed.
    #   This behavior matches the Apache "Deny,Allow" Order directive.
    #   This is the default value.
    #
    #  "Allow,Deny"
    #   The blacklist is only checked when an ip address matches the whitelist.
    #   If the ip address matches both lists, it will be denied. If it matches
    #    neither list, it will be denied.
    #   This behavior matches the Apache "Allow,Deny" Order directive.
    #
    white-black-list-order: "Deny,Allow"
    
    # This is a list of the allowed hostnames (domains) that HTTPConsole will
    #  accept requests on. This means that if someone uses
    #  "http://my.domain.com:8765/console?command=stop" to issue the
    #  stop command to your server, and my.domain.com is not listed below, the
    #  connection will be refused.
    # The one exception to the above rule is that If no hostnames are listed than
    #  any hostname will be allowed.
    # This is similar to virtual hosting except that HTTPConsole only uses the
    #  hostname to allow or deny the request.
    # This feature combined with the cross site scripting restrictions in modern
    #  browsers is designed to make it more difficult for unauthorized people
    #  to target your server from client side (browser) scripts. This does not make
    #  it impossible however as they can always create a proxy if they really want
    #  to send requests from the browser.
    # If any hostnames are listed, requests to bare ip addresses will be denied
    #  unless the ip address is 127.0.0.1.
    # An asterisk (*) in the left most label will match any valid label or labels.
    # At the very least one label and a top level domain (com, org, net, etc.) must
    #  be given per hostname.
    allowed-hosts:
    #   - theanticookie.com
    #   - notch.tumblr.com
    #   - "*.minecraft.net"
    
    # Controls whether connection refused log messages are always sent, or only sent
    #  when log-level is set to info.
    # The default value is false. Connection refused messages will only be visible
    #  if the log-level is set to info.
    always-log-refused-connections: false
    
    Example Backup Bash Script (open)

    This is the backup script I use for my own server.
    Code:
    #!/bin/bash
    BACKUP_DAYS=28
    MINECRAFT_DIR=/home/me/minecraft
    BACKUP_DIR=$MINECRAFT_DIR/backup
    HTTPCONSOLE_URL="http://127.0.0.1:8765"
    
    BASENAME=`basename $0`
    LOCK_FILE=/tmp/$BASENAME.lock
    if [ ! -e "$LOCK_FILE" ]; then
            trap "rm -f \"$LOCK_FILE\"; exit" INT TERM EXIT
            touch $LOCK_FILE
    else
            echo "Backup already running."
            exit
    fi
    
    if [ "$1" == "" ]; then
            echo No worlds specified.
            exit
    fi
    
    TIMESTAMP=`date +%Y-%m-%d_%T`
    
    function console_command
    {
            curl --data-urlencode "command=$*" $HTTPCONSOLE_URL/console
    }
    
    function backup
    {
            WORLD=$1
            SOURCE=$MINECRAFT_DIR/$WORLD/
            TARGET_DIR=$BACKUP_DIR/$WORLD
            TARGET=$TARGET_DIR/$TIMESTAMP
    
            if [ ! -d "$SOURCE" ]; then
                    echo World directory \"$SOURCE\" does not exist.
                    return
            fi
    
            if [ -d "$TARGET_DIR" ]; then
                    if [ -e "$TARGET" ]; then
                            echo Backup path \"$TARGET\" already exists.
                            return
                    fi
    
                    NEWEST_FILE=`ls -t "$TARGET_DIR" 2>/dev/null | head -1`
                    if [ "$NEWEST_FILE" != "" ]; then
                            NEWEST_FILE=$TARGET_DIR/$NEWEST_FILE
                            echo Sourcing Most Recent Backup \"$NEWEST_FILE\"
                            cp -al "$NEWEST_FILE" "$TARGET"
                    else
                            echo No Prior Backups
                    fi
    
                    echo Deleting Backups Older Than $BACKUP_DAYS Days
                    find "$TARGET_DIR/"* -maxdepth 0 -mtime +$BACKUP_DAYS -delete
            elif [ -e "$TARGET_DIR" ]; then
                    echo The backup path \"$TARGET_DIR exists but is not a directory.
                    return
            else
                    mkdir -p "$TARGET_DIR"
            fi
    
            echo Syncing \"$SOURCE\" to \"$TARGET\"
            rsync -a --delete "$SOURCE" "$TARGET"
    }
    
    echo Saving All Minecraft Worlds
    console_command say Backing Up Worlds...
    console_command save-all
    console_command save-off
    echo
    
    for LEVEL in "$@"; do
            echo Backing Up \"$LEVEL\"
            backup $LEVEL
            echo
    done
    
    console_command save-on
    console_command say Backup Complete.
    
    Todo (open)

    • Wait for some log output before completing a request.
    • Return command output.
    • Have the response body be more meaningful than "Recieved Command <command>"
    • Respond to URL or JSON encoded POST requests.
    • Allow the listener address to be changed (not just 127.0.0.1 anymore).
    • Client ip whitelist.
    • Client ip blacklist.
    • Host name filtering.
    • Cookie based sessions. (finished, testing)
    • Get back buffered console output. (finished, testing)
    • Basic/Digest http authorization. (in progress)
    • Command whitelist/blacklist. Allow or disallow some commands.
    • Allow disabling of POST xor GET requests.
    • Write example web page for a console in your browser.
    • Possibly create a new service for restarting the server?
      • Not going to add this because it can be added by getting a plugin that does server restarts and then giving that plugin commands through HTTPConsole.
    • Expose a request handling API to bukkit allowing developers to easily add web service functionality to their plugins.
    • Profit?!
    Change Log (open)


    Version 0.3.0
    • Added blacklist.
    • Added host name filtering.
    • Changed default port to 8765.
    • Bug Fixes
    Version 0.2.1
    • Fixed input stream parsing.
    Version 0.2
    • Reworked logging and output.
    • Handle POST requests (url or json encoded data).
    • Return output from command (easier than I expected).
    • Abstracted a lot of the framework to pave the way for increased future functionality.
    • Listener ip address can be changes via the config.yml file.
    • A client ip address whitelist can be set via the config.yml file.
    Version 0.1
    • Initial Release
     
  2. Offline

    Bambo

    i have a problem...

    Code:
    # The IP address that HTTPConsole will listen on. "any" can be used to listen on
    # any address.
    # The default is 127.0.0.1
    ip-address: any
    
    # The TCP listening port that HTTPConsole will bind to.
    # The default is 8080.
    port: 8080
    
    # Controls how important a console message must be to be shown.
    # Possible values: severe, warning, info
    # The default is severe, meaning only severe log messages will be visible.
    log-level: info
    
    # Controls whether messages beginning with "ConsoleCommandSender:" are filtered
    # out of the console log.
    # The default value is true.
    filter-command-sender: true
    
    # Controls whether connection refused log messages are always sent, or only sent
    # when log-level is set to info.
    # The default value is false. Connection refused messages will only be visible
    # if the log-level is set to info.
    always-log-refused-connections: false
    
    # This sets what ip addresses are allowed to send requests to HTTPConsole.
    # To add more values, just add more "- ip-address" lines to the list.
    # The - with a space after it is important!!!
    # Add - any to the list to allow any ip address to send requests to HTTPConsole.
    # The default is any ip address can send requests to HTTPConsole.
    client-ip-whitelist:
    #   Example:
    #   - 192.168.1.100
        - any
    but when i try to do... http://myserverip:8080/console?command=save-all google chorme says
    Oops! This link appears to be broken.


    Any help?
     
  3. I need a little more info about your server. Linux or windows? Also, do you have a firewall running and have you opened up the port?

    Actually, it looks like something else is answering on that port. Try changing the port from 8080 to something else.

    I think I may change the default to something less commonly used :)

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 13, 2016
  4. Summary, if you don't want to read this whole post.
    • No future HTTPS support planned.
    • Built in web console still planned, but if you open it up to the world then there's a pretty good chance someone will hack your server.
    If you're still reading, I've been looking into giving the plugin HTTPS support. It turns out it's not that hard to do in Java, but the easiest way uses Java key stores, which I don't really want to deal with. I wanted to be able to hand it a PEM and CERT file and go. So, I'm officially taking that off my ideas list. Just not going to go there.

    The reason I was considering it, is that I am planning on building a simple console gui into the plugin. But if I do that, people are going to want to use it when they're not at home, or give access to players they rent servers to remotely, or give themselves console access to servers they rent (which I've been asked about a few times already).

    Sadly, I have to say right now, this plugin by itself is not the way to do that.

    Without HTTPS support, this plugin should never be used to give direct access from the internet. That is not its intended purpose. If you setup the configuration file with no client ip restrictions and have it listen on a port open to the internet, someone will hack your server. When I add basic http auth (if I add it), it might be a little harder, but only slightly. It is not possible to truly secure the console without using ssl.

    So, you might ask, what IS the purpose of this plugin? It's original intended purpose was to add an easy way to access the console from local scripts (bash, batch, perl, php, etc). As an expanded purpose, you could use it to get console access to servers hosted on your local area network. Even that's a little risky, but possibly reasonable.

    The good news is, if you are really really looking for a web based console, this plugin does get you part of the way there. To do it right, you will need an 3rd party web server (Apache for instance), an ssl certificate to be used to setup HTTPS access through that web server, and server side scripts which talk to your minecraft server using this plugin.

    I would like feedback on this issue if you have any. Anything you want to throw out there, I'm open to ideas.
     
  5. Offline

    NynjaWitay

    I setup a simple site with dynmap on one side and your console on the other. I wrapped it up behind a login form and its working great so far with CB677.

    Thanks for your hard work.
     
  6. Offline

    soulreafer

    Nice Jop man.
    I have added an programm for simple using of this Plugin. Interessts?
    check this
     
  7. Oh! nice :D
     
  8. Offline

    Killie01

    can you add this to the TODO:
    a listener, whenever the console says something it sends it to:
    http://serverip:portofplugin/response
    all text stays there intil plugin closes
    that would be useful for UI over http
     
  9. Already on there :) "Get buffered console output (not command related)."
     
  10. Offline

    Killie01

    how do i get that (what url format)
     
  11. it's on the todo list already.
     
  12. Offline

    Killie01

  13. Offline

    NynjaWitay

    I would love this feature. Glad to see you are working on it.
     
  14. Offline

    nacs

    Just wanted to say, this plugin works great -- thanks for making it @BlueJeansAndRain
     
  15. Glad you like it :)
     
  16. Offline

    Zeroi9

    So this could be used on a website, to allow users to /give them elf anything?
     
  17. Yup :)
     
  18. Offline

    piousminion

    Any word on 733 support?

    With this I could replace McMyAdmin with my own custom solution. :D
     
  19. works just fine in 733
     
  20. Offline

    Zeroi9

    Okay, does this also works even if the server isn't running on local? As you got that lined over in the mianpost.
     
  21. yes, it can be configured to listen on more than just local in the config file.
     
  22. Offline

    ks07

  23. Offline

    meeeee

    Hello I am in the process of developing my web GUI for my server as I would like to be able to have control of my server. I am using jquery to send a request ($.get) without reloading but my problem is I cannot catch anything in the return function I wonder if this is because the plugin does not send back anything or I have a problem with my code :) Hope you can answer this soon. If you want me to send you the code please tell me. [edit] I probably have not bothered to check the code properly, but if anyone knows plz reply [edit]
     
  24. Offline

    zonedabone

    You are god. I've been looking for something just like this and found only the telnet client, which was cumbersome, or a wimpy little thing that only did the player list commands. This does everything in a simple and secure way. Time to write a python script!
     
  25. Offline

    johnrazeur

    I love this plugin, but, can you just allow some command, and add option for desactive $_GET and just allow $_POST ?

    Thanks !
     
  26. Ah, good idea! I'll put those on the todo list.
     
  27. Offline

    Phaedrus

    @BlueJeansAndRain


    I love the simplicity of this plugin and it works great, however, I can't rely on a IP whitelist to secure access since my ip addy changes constantly while on the road.

    I suggest maybe adding an option for a rudimentary password protection system, which if enabled in the config and supplied with a predefined password, will only accept commands if the url string contains your password.

    For example:
    http://server.address.com:81021/console?pass=MYPASSWORD?command=save-all

    you're already listening to what's on the line to get the command, it shouldn't be too hard to also listen for the password string and reject any command requests that don't match the preset password.

    Also, on some commands that take a while to process, the console output doesn't get fed back to you.

    For example, if I do "uptodate plugins" craftbukkituptodate will querry it's list for any updated plugins and download them if available, however the feedback isn't returned. I have verified that the command is received and processed.

    Thanks
     
  28. Ya, the password protection is something I've been thinking about.

    The output not getting fed to you is a tricky one. That's due to the plugin doing it's thing asynchronously. There's no way to tell what output comes from which plugin programatically, nor is there a way to tell what plugin handled the command in the first place, so I was relying on plugins dumping out their output in the same thread that handled the command. What I am planning to do is have commands to get the log back to the last request made for the log. So you can poll every second or so and get what's been output to the console since the last request.

    Glad you like it otherwise :).

    Alright, it's been a while since my last update and this one doesn't add a whole lot. I've been busy with my day job and I was trying to come up with a slick IP filtering class that would do really quick lookups on sorted ip ranges. I got tired of that though so it's still just stepping through the list of ranges. It really shouldn't make much of a difference unless you put a massive number (read hundreds) of ranges in the config file, I just like to make things as awesome as possible :).

    There is a blacklist as well as a whitelist for ip addresses now. If you don't know what that means then don't worry about it too much.

    The default port changed to 8765, but because 8080 was written in the config file by default, it won't change unless you delete or modify your config file. This is just to prevent collisions on the very frequently used 8080.

    Host name filtering has been added. This means you can tell HTTPConsole to only listen for requests on specific domains. Say your IP address is 11.22.33.44 and you have yourdomain.com pointed at that address. If you put yourdomain.com in the config file under allowed-hosts, people will only be able to make requests at http://yourdomain.com:8765/console?command=..., and http://11.22.33.44:8765/console?command=... will be rejected. Once again, if you don't see why this is useful, it's probably okay to ignore it :).

    There are also a few bug fixes in the way it handled IP address ranges.

    Now that I'm over the IP address filtering hump, it shouldn't be quite so long before my next update :). Please let me know if you notice any odd behavior in the IP address filtering. I've done basic testing but more testing would certainly be appreciated.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 13, 2016
  29. Offline

    Thom8203dk

  30. Well, just about everything I could tell you I wrote into the configuration file (config.yml) or this thread :). If you have specific questions feel free to ask here so that others can benefit from the Q and A.

    Also, you probably shouldn't post your email address around, though that is a hotmail so maybe it's your spam catcher.

    I haven't used mIRC, but I just did some google-ing. It looks like it should be possible, but the mIRC scripting language doesn't have an HTTP request method per-say, so you have to use sockopen to build an HTTP request string and then parse the http response string.

    All sockopen does on its own is open a socket and then let you read and write to it. HTTP requests are built on top of sockets and have a bunch of text telling the server what you want and providing any relevant context. The response is similar in that it starts out by telling the client what it's going to return and why before actually sending the content.

    I found this script snippet for sending an http request that might be of use to you:
    http://www.mirc.net/projects.php?view_snippet=1123482843

    Here's a pretty good link describing how HTTP requests and responses work:
    http://www.jmarshall.com/easy/http/

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 13, 2016
  31. Offline

    spunkiie

    outstanding plugin
     

Share This Page