I am currently facing the same problem, and my solution is exactly what DuckMaestro and Raven Dreamer suggested - Have a script that creates 4 child objects at runtime each of which representing a side of the border and attach line renderers to each one.
In my case I needed to constantly resize the border to keep it around my object (A text mesh [which uses a mesh renderer] for a custom text field) so every update I did this:
float width = Mathf.Max(renderer.bounds.size.x + paddingX * 2, minWidth);
float x = renderer.bounds.center.x - width / 2;
float height = renderer.bounds.size.y + paddingY * 2;
float y = renderer.bounds.center.y - height / 2;
AlterBorder(0, new Vector3(x - thickness / 2, y, 0), new Vector3(x + width + thickness / 2, y, 0)); //Bottom edge going left to right
AlterBorder(1, new Vector3(x + width, y + thickness / 2, 0), new Vector3(x + width, y + height - thickness / 2, 0)); //Right edge going bottom to top
AlterBorder(2, new Vector3(x + width + thickness / 2, y + height, 0), new Vector3(x - thickness / 2, y + height, 0)); //Top edge going right to left
AlterBorder(3, new Vector3(x, y + height - thickness / 2, 0), new Vector3(x, y + thickness / 2, 0)); //Left edge going top to bottom
AlterBorder() simply accesses the appropriate line renderer (specified by first parameter) and set its start and end to the first and second vector respectively.
Note that I used
renderer as my reference for size, but obviously you can use any rectangle, as long as x,y is the top left corner.
From what I can tell this works really well, looks great in game because I can easily move my bordered object around in all 3 axis (Even rotate it, and since line renderers always face the camera it doesn't look weird), and is not hard to implement.